纯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 相关文章推荐
js调试工具 Javascript Debug Toolkit 2.0.0版本发布
Dec 02 Javascript
javascript mouseover、mouseout停止事件冒泡的解决方案
Apr 07 Javascript
js数值和和字符串进行转换时可以对不同进制进行操作
Mar 05 Javascript
开发中可能会用到的jQuery小技巧
Mar 07 Javascript
javascript基本类型详解
Nov 28 Javascript
浅谈js中的in-for循环
Jun 28 Javascript
AngularJS包括详解及示例代码
Aug 17 Javascript
JS实现图片局部放大或缩小的方法
Aug 20 Javascript
jQuery EasyUI 页面加载等待及页面等待层
Feb 06 Javascript
js html实现计算器功能
Nov 13 Javascript
关于微信小程序登录的那些事
Jan 08 Javascript
微信小程序实现图片翻转效果的实例代码
Sep 20 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 文件上传模型,支持多文件上传
2009/08/13 PHP
php列出一个目录下的所有文件的代码
2012/10/09 PHP
解析CodeIgniter自定义配置文件
2013/06/18 PHP
PHP全局变量与超级全局变量区别分析
2016/04/01 PHP
laravel自定义分页效果
2017/07/23 PHP
Laravel构建即时应用的一种实现方法详解
2017/08/31 PHP
jQuery源码分析-02正则表达式 RegExp 常用正则表达式
2011/11/14 Javascript
jQuery点击tr实现checkbox选中的方法
2013/03/19 Javascript
如何使用Jquery获取Form表单中被选中的radio值
2013/08/09 Javascript
JavaScript优化专题之Loading and Execution加载和运行
2016/01/20 Javascript
理解JavaScript事件对象
2016/01/25 Javascript
关于input全选反选恶心的异常情况
2016/07/24 Javascript
vue2项目使用sass的示例代码
2017/06/28 Javascript
JavaScript编写的网页小游戏,很给力
2017/08/18 Javascript
vscode 插件开发 + vue的操作方法
2020/06/05 Javascript
python通过索引遍历列表的方法
2015/05/04 Python
python基于itchat实现微信群消息同步机器人
2017/02/27 Python
详解js文件通过python访问数据库方法
2019/03/03 Python
Python redis操作实例分析【连接、管道、发布和订阅等】
2019/05/16 Python
numpy库与pandas库axis=0,axis= 1轴的用法详解
2019/05/27 Python
ML神器:sklearn的快速使用及入门
2019/07/11 Python
Python Pandas对缺失值的处理方法
2019/09/27 Python
python 3.7.4 安装 opencv的教程
2019/10/10 Python
Python MySQLdb 执行sql语句时的参数传递方式
2020/03/04 Python
Python使用sqlite3模块内置数据库
2020/05/07 Python
基于Python3读写INI配置文件过程解析
2020/07/23 Python
李宁官方网店:中国运动品牌
2017/11/02 全球购物
印尼披萨外送专家:Domino’s Pizza印尼
2017/12/28 全球购物
荷兰包包购物网站:The Little Green Bag
2018/03/17 全球购物
理肤泉加拿大官网:La Roche-Posay加拿大
2018/07/06 全球购物
销售团队激励口号
2014/06/06 职场文书
2014年教务处工作总结
2014/12/03 职场文书
黄埔军校观后感
2015/06/10 职场文书
六年级作文之家庭作文
2019/12/12 职场文书
nginx网站服务如何配置防盗链(推荐)
2021/03/31 Servers
vue 给数组添加新对象并赋值
2022/04/20 Vue.js