原生js canvas 碰撞游戏的开发笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生js canvas 碰撞游戏的开发笔记相关的知识,希望对你有一定的参考价值。
-----------------------------------------------福利---------------------------------------------
-----------------------------------------------分割线---------------------------------------------
今天 我们研究下碰撞游戏
什么是碰撞游戏? 当然是东西碰到在一起啦 用前端逻辑来说 就是2个物品互相碰撞产生的事件
问多无用 先扫下二维码体验下( 欢乐斗地主接元宵)
很简单 也很实用的碰撞吧 (虽然也很无聊)
不过我理念里是碰撞游戏用类似cocos2d 或者createJS 这种游戏引擎才能写 。不过谁叫咱只会原生js和jquery zepto哈
我尝试写了这个游戏 并且与大家分享分享思路。
首先这不是我第一次写碰撞游戏。 但以前写的碰撞游戏 都是以dom方法生成的 总之十分的卡! 卡!
这次换成canvas 做 。果然非常流畅
我的基本思路是 游戏流程是个对象 ,游戏里的动态元素(道具 人物)是对象 ,游戏里的静态元素(背景 装饰品)是dom元素
那么这样就产生了 用div 建立背景之类 。用canvas drawImage方法去生成汤圆之类的
dom这块我不用说了 右键查看下源码就知道怎么布局 主要想分析下canvas生成
在canvas中的所谓的落下 并不是像animate 线性变化那么简单
它拆分了好几块 创建元素 插入元素 更新元素 循环。。 熟悉帧动画的人比较熟悉 我们看到的动画 是无数细微变化的动画 快速组成的!
越是细小 动画越流畅 这也就是我们常说的fps. (打游戏卡)
_createCavaseEle:
这个方法是专门用来创建元素的 。当然应该叫做创建对象比较好。 因为元素只是张img的话是无法移动 判断的
SteinsGate(名字很亮吧)是个构造函数 返回1个元素对象 此对象含有些必要的的属性 对应后面的逻辑判断!
1 var SteinsGate=function(pic,type){ 2 if(!pic){return "undefined";} 3 var that=this; 4 this.tag=pic[0]; 5 this.img=new Image(); 6 this.src=pic[1]; 7 this.width=pic[2]; 8 this.height=pic[3]; 9 this.x=pic[4]; 10 this.y=pic[5]; 11 this.LastX=this.x 12 this.LastY=this.y; 13 this.collide=false; 14 this.down=false; 15 16 if(type=="dom"){//dom生成 17 if(!document.getElementById(this.tag)){ 18 var farmer=document.createElement("div"); 19 }else{ 20 var farmer=document.getElementById(this.tag); 21 } 22 farmer.id=this.tag; 23 farmer.className=this.tag; 24 farmer.style.left=this.x+"px"; 25 26 farmer.style.top=this.y+"px"; 27 28 $(".lovelive").append(farmer); 29 } 30 else{//canvas生成 31 this.loadimg=function(){ 32 that.img.src=that.src; 33 that.img.onload = function () { 34 _this._upDateEle(that,this.x,this.y); //_this是个闭包 指向外面的CollideGame 35 } 36 37 }(); 38 } 39 40 }
这里原本只有canvas生成 但是后面因为清除图像时候 也会把农民也给清除 所以农民这个对象是 数据还是canvas数据 图像是由dom生成
不知道各位有没有更好的方法? 不要写2个canvas标签哦 破坏布局美感的
_ctrlGame
这个方法是游戏的主逻辑程序;
为每个刚刚建立的元素添加基本属性(汤圆or王炸) 基本事件 (控制or下落)
并且全局控制游戏进程 _ctrlDownItem(控制掉落物) _ctrlFarmer(控制农民)
请注意 这个方法还是没有在canvas里生成图像 。生成是在控制所调用_upDateEle方法里
_ctrlDownItem 和 _ctrlFarmer
载入设定好的参数 和布局属性(canvas高啊 canvas宽啊) 并且为对象的绑定对应事件( 掉落的话就绑定碰撞 落地 or 控制就触摸事件)
在这些对应事件里又有分各种细节的逻辑判断
_isCollide 和_isGround 和_canvas_touchmove
这些都是细节对应的逻辑判断 具体原理请看源码 值得一提的是 上来touchmove我老是坐标不对 研究半天 原来发现手机屏幕大小和页面wrap大小不是1:1 经过对等换算就能解决啦
在这些判断后最后执行更新画布_upDateEle (请注意 这里还是没有生成图像!!)
_upDateEle
原理很简单 只有满足的条件的才能生成图像 所有的条件在上面的判断已经生效!!
在这里别忘了 canvas的clearRect方法先清除上次的残留图像 在从新画
1 //更新元素pos 2 _upDateEle:function(ele,x,y,type){ //ele:元素 x:元素的x坐标 y:元素的y坐标 type:绘制方法(默认) 3 if(type=="dom"){ 4 //更新X坐标; 5 6 if(x){ele.x=x;} 7 //更新Y坐标; 8 if(y){ele.y=y;} 9 10 document.getElementById(ele.tag).style.left=ele.x+"px"; //更新图像 11 document.getElementById(ele.tag).style.top=ele.y+"px"; 12 ele.LastX=ele.x; 13 ele.LastY=ele.y; 14 }else{//Canvas 15 _this.ctx.clearRect(ele.LastX, ele.LastY,ele.width,ele.height); 16 //满足以下条件 才可以绘制 17 if(ele){ //是否有元素 18 if(!ele.down){ //是否已落地 19 if(!ele.collide){ //是否发生碰撞 20 //更新X坐标; 21 if(x){ele.x=x;} 22 //更新Y坐标; 23 if(y){ele.y=y;} 24 _this.ctx.drawImage(ele.img,ele.x,ele.y,ele.width,ele.height); 25 ele.LastX=ele.x; 26 ele.LastY=ele.y; 27 } 28 } 29 } 30 31 32 } 33 34 },
至此 整个游戏函数构造完成 接下来就是 把控各个参数 原理还是老样子
创建对象-》插入对象-》更新对象(满足条件的才有图像 )
当对象的活动结束后别忘了 垃圾回收 =null哦
其实看到这可能大家还有些疑问 但我自己也不确信这些是不是很好的方法 比如
makikulisi() 我的原理是把 元素的运动的整个动画 拆分很多画面帧 然后递归的setTimeout(16毫秒)去刷新帧 达到帧动画效果
在游戏框架里也许有更好的方法吧?
isCollide()我一开始用的是老方法 (这个老方法 我研究了足足有1天!!)但网上查了资料 canvas好像也有那么神奇的isPointInPath方法 而且很有效
因为过于神奇 和老方法的辛酸 所以我也很吃不准 这个是不是有bug?
总之 整个制作过程 自己也不可思议 我刚写时候 我还觉得我写不出呢(不会框架!)
但是写着写着就写出来了。。。 真是船到桥头自然直
希望对你以后制作这种类型的游戏有所帮助 不会不要怕 原生js也能写!
附 源码
以上是关于原生js canvas 碰撞游戏的开发笔记的主要内容,如果未能解决你的问题,请参考以下文章