纯HTML5制作围住神经猫游戏-附源码下载


Posted in Javascript onAugust 23, 2015

HTML5围住神经猫游戏网页版是一款基于HTML5、jquery、Typescript等技术制作的围住神经猫游戏。

先给大家附上演示和源码下载,点击这里  查看演示     下载源码

去年风靡微信朋友圈的小游戏“围住神经猫”,我也试着做了一下。游戏是用Egret引擎开发的,因为Egret是用Typescript语言构建的,因此这里游戏也是用Typescript来开发的。

游戏规则:

点击画面上的灰色格子,慢慢将神经猫围起来抓住。如果猫到达游戏区边缘则游戏失败。

准备素材

在网上搜索“围住神经猫”游戏,打开一个,并打开调试界面,从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}
 }}

编写代码

主要总结下我在开发过程中遇到的主要的两个难题。

问题一,猫该如何逃跑?

在这个游戏中,每个圆圈都可能有三种状态

可通行,灰色圆圈表示

有路障,不可行,橙色圆圈表示

被猫占领,灰色圆圈,猫的动画叠置于其上

每当点击了灰色圆圈,就会将其变成橙色圆圈即路障状态,同时猫会紧跟着点击的动作也向周边走一步。

行走方向

游戏区由9*9个圆圈组成,偶数行缩进圆圈半径大小的宽度,这样的布局导致,猫理论上可以有6个行走方向(每次只能走一步),分别是左,左上,右上,右,右下,左下,如这些位置上的圆圈为路障状态,则相应方向不可通行。

如果这六个方向的邻居有五个都为路障,那当然很好选择线路,剩下的那个就是唯一的出路了,但是显然情况不可能如此简单。我们遇到的更多的情况是,六个方向的邻居上,有直接为路障状态的(那自然绝对不走这一步),有是可通行状态的,但是彼此向边缘的可达性不同。

 纯HTML5制作围住神经猫游戏-附源码下载

比如上图中,目前,猫的左方向走三步即可到达边缘,右上、右下向走四步可达,左上、右方向上可走一步但即遇路障,左下方向走三步遇路障。这时候我们当然应该为这六个方向的优先级排个序。

优先级

我是这样设定优先级顺序的:

一路通行的方向>会出现路障的方向,如此图中左、右上、右下>左上、右、左下

一路通行的方向中,离边缘越近优先级越高,如此图中左>右上、右下

会出现路障的方向中,可走的步数越多优先级越高,如此图中左下>右、左上

下面将这些约定的可达性用数值来体现以便比较,设这个值为accessibility,值越大优先级越高。

一路通行的方向

accessibility = 1/stepToEdge; //stepToEdge表示离边缘还有几步

会出现路障的方向

accessibility = (-1)/stepToBlock;//stepToBlock表示离路障的距离

接下来考虑分母如果为0怎么办,在第一种情况中,分母为0,表示猫当前已经在边缘了,那么也不用判断优先级了,游戏已经失败了。第二种情况中,分母为0表示出门即遇路障,这个方向不用考虑了是绝对走不通的,那么它的优先级就定为-1。

这样一轮算下来,六个方向上的accessibility值分别为:

左:1/3

左上:-1

右上:1/4

右:-1

右下:1/4

左下:-1/3

这样比较下来优先级应该是左>右上>右下>左下>左上>右。

为什么左上与右,右上与右下,这两组内部的值明明一样,我们依然是排出了顺序呢?只是因为我们计算是从左方向开始顺时针旋转的。如果值一样,那就看出现的顺序了。

所以在上图中这种情况下,猫会向左走一步。

问题二,如何判断猫被围住了?

在网上玩这个游戏的时候,我发现当猫被围住的时候会换成一种“被围住”的动作,那么该如何判断猫被围住了,然后改变它的动作动画?

“被围住”与“被抓住”不一样,它早于“被抓住”的状态。当猫无路可走的时候,它就“被抓住”了,游戏获胜。而“被围住”指的是猫暂时还有路可走,但是已经被包围住了,垂死挣扎而已,如下图。

 纯HTML5制作围住神经猫游戏-附源码下载

我的思路是这样的:

从猫当前的位置找六个方向中可通行的邻居,然后从这些邻居出发,再找它们各自的可通行邻居,一直这样找下去,一边找的过程中,一边判断当前已经找到的邻居中有没有处在游戏区边缘的,如果有,那么寻找过程提前结束,判断结果是:猫没有被围住。如果直到所有的可通行邻居都找到了,里面都没有处在游戏区边缘的,那么判断结果是:猫被围住了。
接下来用代码实现这个判断过程。

首先,需要准备一个方法,判断圆圈是否已经处在圆圈边缘了,假设这个方法名及参数如下,内部实现比较简单这里就不贴了。

/*
判断传入的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,猫被围住了,它的直接邻居及众多间接邻居中没有一个是在边缘的。

Javascript 相关文章推荐
javascript返回顶部效果(自写代码)
Jan 06 Javascript
jQuery:节点(插入,复制,替换,删除)操作
Mar 04 Javascript
js动态删除div元素基本思路及实现代码
May 08 Javascript
基于jQuery Tipso插件实现消息提示框特效
Mar 16 Javascript
Javascript自执行匿名函数(function() { })()的原理浅析
May 15 Javascript
js精准的倒计时函数分享
Jun 29 Javascript
JavaScript DOM 对象深入了解
Jul 20 Javascript
jQuery 全选 全部选 反选 实现代码
Aug 17 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
Jul 13 Javascript
Angular 容器部署的方法
Apr 17 Javascript
Vue 实现手动刷新组件的方法
Feb 19 Javascript
Vue+Element实现表格编辑、删除、以及新增行的最优方法
May 28 Javascript
javascript中Array()数组函数详解
Aug 23 #Javascript
jquery+css实现的红色线条横向二级菜单效果
Aug 22 #Javascript
js实现的二级横向菜单条实例
Aug 22 #Javascript
JS实现网页顶部向下滑出的全国城市切换导航效果
Aug 22 #Javascript
jquery实现点击向下展开菜单项(伸缩导航)效果
Aug 22 #Javascript
jquery实现很酷的网页顶部图标下拉菜单效果
Aug 22 #Javascript
jQuery实现向下滑出的二级菜单效果实例
Aug 22 #Javascript
You might like
php array_merge下进行数组合并的代码
2008/07/22 PHP
PHP array_flip() 删除重复数组元素专用函数
2010/05/16 PHP
PHP调用C#开发的dll类库方法
2014/07/28 PHP
一段实用的php验证码函数
2016/05/19 PHP
php技巧小结【推荐】
2017/01/19 PHP
PHP将整数数字转换为罗马数字实例分享
2019/03/17 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
关于textarea提交的内容无法换行的解决办法
2013/04/09 Javascript
javascript中通过arguments参数伪装方法重载
2014/10/08 Javascript
form.submit()不能提交表单的原因分析
2014/10/23 Javascript
浅析javascript的间隔调用和延时调用
2014/11/12 Javascript
原生js实现的贪吃蛇网页版游戏完整实例
2015/05/18 Javascript
js中javascript:void(0) 真正含义
2020/11/05 Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
2016/02/23 Javascript
Bootstrap被封装的弹层
2016/07/20 Javascript
详解jQuery简单的表格应用
2016/12/16 Javascript
javascript基本数据类型和转换
2017/03/17 Javascript
在ABP框架中使用BootstrapTable组件的方法
2017/07/31 Javascript
微信小程序和百度的语音识别接口详解
2019/05/06 Javascript
JS数据类型判断的几种常用方法
2020/07/07 Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
2020/08/14 Javascript
Python实现的石头剪子布代码分享
2014/08/22 Python
详解用Python处理HTML转义字符的5种方式
2017/12/27 Python
Python下载网络文本数据到本地内存的四种实现方法示例
2018/02/05 Python
pyqt5之将textBrowser的内容写入txt文档的方法
2019/06/21 Python
python构造函数init实例方法解析
2020/01/19 Python
Python IDE环境之 新版Pycharm安装详细教程
2020/03/05 Python
HTML5 Convas APIs方法详解
2015/04/24 HTML / CSS
捐款倡议书格式范文
2014/05/14 职场文书
干部作风建设心得体会
2014/10/22 职场文书
幼儿园小班个人总结
2015/02/12 职场文书
小学生学习保证书
2015/02/26 职场文书
格列佛游记读书笔记
2015/06/30 职场文书
教育教学读书笔记
2015/07/02 职场文书
MySQL安装后默认自带数据库的作用详解
2021/04/27 MySQL
html5调用摄像头实例代码
2021/06/28 HTML / CSS