全部文章搬运自个人我的主页:sheilasun.mehtml
去年风靡微信朋友圈的小游戏“围住神经猫”,我也试着作了一下,能够戳这里试玩→围住神经猫。游戏是用Egret引擎开发的,由于Egret是用Typescript语言构建的,所以这里游戏也是用Typescript来开发的。git
完整的代码能够戳个人Github→sheila1227/HTML5-GAME-shenjingcatgithub
点击画面上的灰色格子,慢慢将神经猫围起来抓住。若是猫到达游戏区边缘则游戏失败。json
在网上搜索“围住神经猫”游戏,打开一个,并打开调试界面,从network中或者resource中把猫、灰色圆圈、橙色圆圈等图片扒下来保存到本地。
须要注意的是,Egret新的MovieCilp架构设计以及MovieClip数据格式标准都与早期有些不一样,我从网上扒下来的已经不适用了,根据新的数据格式标准作修改后mc的json文件以下:数组
{"mc":{ "stay":{ "frameRate":20, "labels":[], "frames":[ {"res":"stay0000","x":0,"y":0}, {"res":"stay0001","x":0,"y":0}, {"res":"stay0002","x":0,"y":0}, {"res":"stay0003","x":0,"y":0}, {"res":"stay0004","x":0,"y":0}, {"res":"stay0005","x":0,"y":0}, {"res":"stay0006","x":0,"y":0}, {"res":"stay0007","x":0,"y":0}, {"res":"stay0008","x":0,"y":0}, {"res":"stay0009","x":0,"y":0}, {"res":"stay0010","x":0,"y":0}, {"res":"stay0011","x":0,"y":0}, {"res":"stay0012","x":0,"y":0}, {"res":"stay0013","x":0,"y":0}, {"res":"stay0014","x":0,"y":0}, {"res":"stay0015","x":0,"y":0} ] }}, "res":{ "stay0000": {"x":0,"y":0,"w":61,"h":93}, "stay0001": {"x":61,"y":0,"w":61,"h":93}, "stay0002": {"x":122,"y":0,"w":61,"h":93}, "stay0003": {"x":183,"y":0,"w":61,"h":93}, "stay0004": {"x":0,"y":93,"w":61,"h":93}, "stay0005": {"x":61,"y":93,"w":61,"h":93}, "stay0006": {"x":122,"y":93,"w":61,"h":93}, "stay0007": {"x":183,"y":93,"w":61,"h":93}, "stay0008": {"x":0,"y":186,"w":61,"h":93}, "stay0009": {"x":61,"y":186,"w":61,"h":93}, "stay0010": {"x":122,"y":186,"w":61,"h":93}, "stay0011": {"x":183,"y":186,"w":61,"h":93}, "stay0012": {"x":0,"y":279,"w":61,"h":93}, "stay0013": {"x":61,"y":279,"w":61,"h":93}, "stay0014": {"x":122,"y":279,"w":61,"h":93}, "stay0015": {"x":183,"y":279,"w":61,"h":93} }}
主要总结下我在开发过程当中遇到的主要的两个难题。微信
在这个游戏中,每一个圆圈均可能有三种状态架构
每当点击了灰色圆圈,就会将其变成橙色圆圈即路障状态,同时猫会紧跟着点击的动做也向周边走一步。app
游戏区由9*9个圆圈组成,偶数行缩进圆圈半径大小的宽度,这样的布局致使,猫理论上能够有6个行走方向(每次只能走一步),分别是左,左上,右上,右,右下,左下,如这些位置上的圆圈为路障状态,则相应方向不可通行。
若是这六个方向的邻居有五个都为路障,那固然很好选择线路,剩下的那个就是惟一的出路了,可是显然状况不可能如此简单。咱们遇到的更多的状况是,六个方向的邻居上,有直接为路障状态的(那天然绝对不走这一步),有是可通行状态的,可是彼此向边缘的可达性不一样。
布局
我是这样设定优先级顺序的:动画
下面将这些约定的可达性用数值来体现以便比较,设这个值为accessibility,值越大优先级越高。
一路通行的方向
accessibility = 1/stepToEdge; //stepToEdge表示离边缘还有几步
会出现路障的方向
accessibility = (-1)/stepToBlock;//stepToBlock表示离路障的距离
接下来考虑分母若是为0怎么办,在第一种状况中,分母为0,表示猫当前已经在边缘了,那么也不用判断优先级了,游戏已经失败了。第二种状况中,分母为0表示出门即遇路障,这个方向不用考虑了是绝对走不通的,那么它的优先级就定为-1。
这样一轮算下来,六个方向上的accessibility值分别为:
这样比较下来优先级应该是左>右上>右下>左下>左上>右。
为何左上与右,右上与右下,这两组内部的值明明同样,咱们依然是排出了顺序呢?只是由于咱们计算是从左方向开始顺时针旋转的。若是值同样,那就看出现的顺序了。
因此在上图中这种状况下,猫会向左走一步。
在网上玩这个游戏的时候,我发现当猫被围住的时候会换成一种“被围住”的动做,那么该如何判断猫被围住了,而后改变它的动做动画?
“被围住”与“被抓住”不同,它早于“被抓住”的状态。当猫无路可走的时候,它就“被抓住”了,游戏获胜。而“被围住”指的是猫暂时还有路可走,可是已经被包围住了,垂死挣扎而已,以下图。
个人思路是这样的:
从猫当前的位置找六个方向中可通行的邻居,而后从这些邻居出发,再找它们各自的可通行邻居,一直这样找下去,一边找的过程当中,一边判断当前已经找到的邻居中有没有处在游戏区边缘的,若是有,那么寻找过程提早结束,判断结果是:猫没有被围住。若是直到全部的可通行邻居都找到了,里面都没有处在游戏区边缘的,那么判断结果是:猫被围住了。
接下来用代码实现这个判断过程。
首先,须要准备一个方法,判断圆圈是否已经处在圆圈边缘了,假设这个方法名及参数以下,内部实现比较简单这里就不贴了。
/* 判断传入的circle是否在边界上 */ private isCircleAtEdge(circle:Circle):boolean { ... }
再准备一个方法,获取某圆圈周围某方向的邻居。
private getCircleNeighbor(circle:Circle,direction:Direction):Circle{ ... }
最后,是判断的核心方法。
/* 可否在circle位置出发找到路线到达边缘 */ private canExitAt(circle:Circle):boolean{ var ignoreArr=[];//不用再处理的circle集合 var toDealWithArr=[circle];//还需进行判断的circle集合 while(true){ if(toDealWithArr.length<1){ return false; }else{ var _first=toDealWithArr.shift(); ignoreArr.push(_first); if(_first.getStatus()!==CircleStatus.Blocked&&this.isCircleAtEdge(_first)){ return true; }else{ for(var i=Direction.LEFT;i<=Direction.BOTTOM_LEFT;i++){ var nbr=this.getCircleNeighbor(_first,i); if(!(ignoreArr.indexOf(nbr)>-1||toDealWithArr.indexOf(nbr)>-1)) if(nbr.getStatus()!==CircleStatus.Available){ ignoreArr.push(nbr); }else{ toDealWithArr.push(nbr); } } } } } }
在方法体的最开始,准备好两个数组,一个用来存储不用再处理的圆圈集合ignoreArr,另外一个用来存储还须要进行判断的圆圈集合toDealWithArr。每找到一个可通行的邻居,首先要判断它是否是第一次出现(由于几个圆圈可能会有共同的邻居,因此一个圆圈可能由于它是多个圆圈的邻居而被找到屡次),判断的标准就是它有没有出如今ignoreArr或toDealWithArr里,若是没有那么就是第一次出现,若是它是路障,那么塞到ignoreArr,若是不是路障,那么推入toDealWithArr尾部等待判断。
每次循环开始时,咱们会从toDealWithArr头部弹出一个圆圈对象,对它是否在边缘作判断,若是是,那么返回true跳出循环,猫没有被围住,它能够经过某条路线到达边缘。若是toDealWithArr所有判断完了都不在边缘,那么返回false,猫被围住了,它的直接邻居及众多间接邻居中没有一个是在边缘的。
完整的代码能够戳个人Github→sheila1227/HTML5-GAME-shenjingcat
在线试玩能够戳→围住神经猫
有任何不妥之处或错误欢迎各位指出,不胜感激~