DOM+CSS3实现小游戏SwingCopters
前些日子看到了一则新闻,flappybird原作者将携新游戏SwingCopters来袭,准备再靠这款姊妹篇游戏引爆大众眼球。就是下面这个小游戏:
三四天后,原作者的SwingCopters貌似没怎么火起来,看来flappybird的神话只是一个偶然呀~不过我的山寨版倒是有模有样的做出来了,点这里查看Demo,请在chrome下打开, 你懂的。
(function(){
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
}
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) {
clearTimeout(id);
}
}());
下面我把一些技术细节来介绍下,介于小弟也是第一次做游戏,有些地方的实现不免走了弯路,或者损耗性能,有大牛发现了请一定赐教~
先从最简单的来说起吧,首先需要一个div来做整个游戏的容器,由于游戏要能在手机上玩,所以宽高就必须做成自适应的,那么viewport的设置是必不可少的:
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
html, body{
height: 100%;
position: relative;
margin:;
overflow: hidden;
-webkit-user-select:none;
}
接下来是容器container的样式:
#container{
height: 100%;
position: relative;
overflow: hidden;
}
另外,为了让游戏在PC浏览器中也可以玩,我又用媒体查询做了如下设置:
@media screen and (min-width: 1024px) {
#container{
width: 360px;
margin: 0 auto;
}
}
游戏的容器container有一个背景图片,这个背景图片是需要连续且无限滚动的。首先,图片纵向平铺嘛,一个background-repeat: repeat-y;搞定。原先我考虑这么简单的运动用css3肯定能做的啦,但细细考虑之后发现竟然实现不了。。。假设在keyframes中设置关键帧,改变background-position来实现背景移动,移动倒是没问题,关键是这个连续无限滚动比较棘手,要连续滚动必须给一个很大的值才行,background-position需要设为多大才算无限呢?天知道玩家能玩多长时间,而且这样做显然是不合理的。或者把动画的播放次数设为infinite呢?这也不行,因为每次循环都会从头开始播放一遍,这样背景会闪动。所以最终还是把背景的移动放在js中来操作了,用一个变量来记录背景的位置,然后在主线程中不断递增。大概的代码结构是这样子的:
var game = {
bgMove : function(){
posMark += 2;
container.css('background-position', '0 '+posMark+'px');
timmer = requestAnimationFrame(game.bgMove);
}
}

@-webkit-keyframes flyr{
0%{
background-position: 0 0;
}
100%{
background-position: -108px 0;
}
}
.flyr{
-webkit-animation:flyr 200ms steps(2) 0 infinite;
}
@-webkit-keyframes up{
0%{
bottom:;
}
100%{
bottom: 44%;
}
}
.flyl{
-webkit-animation:flyl 200ms steps(2) 0 infinite, up 4s linear 0 1 normal forwards;
}
@-webkit-keyframes mover{
0%{
left :;
}
100%{
left : 100%;
}
}
.flyl{
left: 0 !important;
-webkit-animation:flyl 200ms steps(2) 0 infinite, up 4s linear 0 1 normal forwards;
}
.flyr{
left: 100% !important;
-webkit-animation:flyr 200ms steps(2) 0 infinite, up 4s linear 0 1 normal forwards;
}
-webkit-transition : left 1.5s 0 linear;
$(document).on('click', function(){
if(++direction%2==0){
player[0].className = 'flyl';
}
else{
player[0].className = 'flyr';
}
});
-webkit-transform-origin:center 4px;
bgMove : function(){
game.generateHand();//产生横梁
posMark += 2;
container.css('background-position', '0 '+posMark+'px');
var hands = $('.hand_l, .hand_r');
hands.each(function(index, element){
var _this = $(this),
thisTop = parseInt(_this.css('top'));
if(thisTop>cHeight){
_this.remove();
}
else{
thisTop += 2;
_this.css('top', thisTop+'px');
}
if(thisTop>player.offset().top+e1H){
//已经位于下方
if(!_this.data('pass') && index%2==0){
scroeC.text(++score);
_this.data('pass', 1);
}
}
else{
//碰撞检测
if(game.impactCheck(player, _this.find('.t'))){
game.stop();
return false;
}
}
});
timmer = requestAnimationFrame(game.bgMove);
}
isMobile : function(){
var sUserAgent= navigator.userAgent.toLowerCase(),
bIsIpad= sUserAgent.match(/ipad/i) == "ipad",
bIsIphoneOs= sUserAgent.match(/iphone os/i) == "iphone os",
bIsMidp= sUserAgent.match(/midp/i) == "midp",
bIsUc7= sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4",
bIsUc= sUserAgent.match(/ucweb/i) == "ucweb",
bIsAndroid= sUserAgent.match(/android/i) == "android",
bIsCE= sUserAgent.match(/windows ce/i) == "windows ce",
bIsWM= sUserAgent.match(/windows mobile/i) == "windows mobile",
bIsWebview = sUserAgent.match(/webview/i) == "webview";
return (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM);
}
var eventType = this.isMobile() ? 'touchstart' : 'click';
$(document).on(eventType, function(){
if(++direction%2==0){
player[0].className = 'flyl';
}
else{
player[0].className = 'flyr';
}
});
<a id="share" href="javascript:(function(){window.open('http://v.t.sina.com.cn/share/share.php?title=网页版SwingCopters,来,看看你有多挫&url=idoube.com/proj/SwingCopters&source=bookmark&pic=http%3A%2F%2Fidoube.com%2Fproj%2FSwingCopters%2FSwingCopters%2Fshot.jpg','_blank','width=450,height=400');})()">分享到微博</a>
DOM+CSS3实现小游戏SwingCopters的更多相关文章
- css3+jquery+js做的翻翻乐小游戏
主要是为了练习一下css3的3D翻转功能,就做了这么个小游戏,做的比较粗糙,但是效果看的见. 主要用到的css3代码如下: html结构: <div class="container& ...
- 制作动画或小游戏——CreateJS事件(二)
在Canvas中如果要添加事件,就需要计算坐标来模拟各种事件,而EaselJS中已经封装好了多个事件,只需调用即可. 一.事件 1)点击 事件是绑定在Shape类中的,click事件与DOM中的意思是 ...
- JS实现别踩白块小游戏
最近有朋友找我用JS帮忙仿做一个别踩白块的小游戏程序,但他给的源代码较麻烦,而且没有注释,理解起来很无力,我就以自己的想法自己做了这个小游戏,主要是应用JS对DOM和数组的操作. 程序思路:如图:将游 ...
- 使用Vue编写点击数字小游戏
使用vue编写一个点击数字计时小游戏,列入你在文本框中输入3,点击开始会生成一个3行3列的表格,表格数据为1-9随机排列,这时候从1开始点击,按顺序点到9,当按正确顺序点击完毕,会提示所用的时间,如果 ...
- 原生javascript开发仿微信打飞机小游戏
今天闲来无事,于是就打算教一个初学javascript的女童鞋写点东西,因此为了兼顾趣味性与简易程度,果断想到了微信的打飞机小游戏.. 本来想用html5做的,但是毕竟人家才初学,连jquery都还不 ...
- flappy pig小游戏源码分析(1)——主程序初探
闲逛github发现一个javascript原生实现的小游戏,源码写的很清晰,适合想提高水平的同学观摩学习.读通源码后,我决定写一系列的博客来分析源码,从整体架构到具体实现细节来帮助一些想提高水平的朋 ...
- “倔驴”一个h5小游戏的实现和思考(码易直播)——总结与整理
3月23日晚上8点半(中国队火拼韩国的时候),做了一期直播分享.15年做的一个小游戏,把核心代码拿出来,现场讲写了一遍,结果后面翻车了,写错了两个地方,导致运行效果有点问题,直播边说话边写代码还真不一 ...
- 浅试 Webview 一app 加载 H5小游戏
整体架构: InventionActivity:实现UI的实例化,基本的按钮Activity之间跳转 GameActivity:实现UI的实例化,Webview的基本使用 MyProgressDial ...
- 例子:js超级玛丽小游戏
韩顺平_轻松搞定网页设计(html+css+javascript)_第34讲_js超级玛丽小游戏_学习笔记_源代码图解_PPT文档整理 采用面向对象思想设计超级马里奥游戏人物(示意图) 怎么用通过按键 ...
随机推荐
- 《UML大战需求分析》阅读笔记4
流程分析利器之二,状态机图. 状态机图也可以叫状态图,也是用来分析流程的,之前的活动图的主体是事件的行为,而状态机图主要描述的是事件的状态. 开始:实心圆点: 结束:点加环:(与活动图一样) 状态:圆 ...
- linux下安装oracle
一>1.关闭防火墙,禁用selinux vi /etc/selinux/config 修改SELINUX=disabled,然后重启,如果不想重启使用命令setenforce 0 2.安装依赖 ...
- 批量创建SQL Server分区文件
) declare @i int set @table = 'v3_yqsd_report' begin exec('alter database '+@table+' add filegroup O ...
- openssl证书制作详细教程
自签名证书及验证 模拟证书涉及的角色 创建证书目录 mkdir ~/certs cd ~/certs 认证机构.网站.浏览器/用户 mkdir root web user 机构自签名证书生成和发布 生 ...
- u3d avatar部件的理解
u3d中带动画的fbx文件导入的时候,就会显示一个avatar组件,这个到底干嘛的一直没能很好的理解,翻看网上的介绍,基本都是告诉你,设置humanoid类型动画时,拖拉过去之类,但是这玩意到底存储了 ...
- Excel里内嵌在线翻译
本来寻思着继续写点系统运行日志跟踪技术的,但早晨哥家领导从单位打来电话,让帮助她的闺蜜搞一个excel翻译的问题,总部IT搞不定.我过去是用excel做了几年工作,却都是些数学计算,跟翻译也扯不上啊: ...
- 转载:JProfiler远程监控LINUX上的Tomcat过程细讲
来源于xuwanbest的博客 所谓"工欲善其事,必先利其器",好的工具确能起到事半工倍的作用.我用到的最多的就两个JConsole 和JProfiler .JConsole监 ...
- struts2中jsp前台传值到后台action的方法(转)
在Struts2中jsp前台传值到action后台的方法 分类: java2012-02-28 13:58 2171人阅读 评论(1) 收藏 举报 actionstrutsjspgetterstrin ...
- 浅谈Swift集合类型
Swift 的集合表现形式由数组和字典组成.它可以完美的存储任何呢想存储的东西. 数组是一个同类型的序列化列表集合,它用来存储相同类型的不同值.字典也是一个数组,但它的存值方式类似于Map,通过一对一 ...
- easyui的datagrid多次调用action的原因
今天碰见一个非常奇怪的问题,一个页面的datagrid正常,另一个页面的datagrid两次调用action代码,比较两个页面datagrid的使用方法,并没有不同.后经仔细debug,发现问题所在: ...