18
2015
11

(十二)createjs游戏-围住神经猫

上一篇搭建好了一个游戏框架。接下来就要用框架做一些游戏了。

2014年,《围住神经猫》火了一把,html5游戏,egret也跟着火了。

其实这个游戏很早就有了,原作者是日本人。最初的版本(我见过的最早的)是用as2写的。通过破解swf文件,得到了一个网址:http://www.gamedesign.jp/这个可能是原作者的网站。(如有错误,欢迎指正)

其实,有好多很好玩的flash小游戏。国外原创的居多,国内大多数都是抄袭的,当然也不乏原创的好作品。

http://hanyeah.com/coolSite.html这里搜集了一些好玩的小游戏,以及一些小游戏网站。也可以直接看这里http://www.zhihu.com/question/21182817

本来想着用air直接移植到手机上,但是发现好多都是as2时代的作品,air貌似不支持as2,只好作罢。


不说废话了,开始介绍游戏的实现。

由于代码略多,作者本身逻辑也比较混乱,想到哪写到哪,写完自己都忘了怎么做的了。所以不详细解释了,只说说一些比较重要的地方。具体实现可下载源文件来看。


假设你已经下载好了之前的模板

1)修改index.html。

只需要修改canvas的宽高,以及title。作者把宽高修改成了height="480" width="800",做完后发现手机上不太合适,也不好改了。

2)修改HResources.js。

修改之前,应该已经准备好了图片素材以及声音素材。

3)修改HGame.js。

HGame.data中的变量做了修改。

逻辑和之前的模板略有不同,所以需要稍作修改。游戏结束的时候,有两种情况,一种是游戏失败,一种是游戏成功。游戏成功的话,结束界面应该有一个“继续挑战”按钮,点击之后,直接进入游戏界面,游戏失败,才是之前模板中的逻辑。

结束界面增加了一个侦听overLayer.addEventListener("nextLevel",nextLevel);实现了nextLevel函数。不回到开始界面,而是直接进入下一关。

4)修改HMenuLayer.js、HOverLayer.js。

这两个界面主要就是摆放一些可视元件,侦听按钮点击,发送事件。

可视元件无非是:文本框、位图、矢量图,复杂一点的有按钮、动画。

文本可以用HUtils.createText来实现,自己做了封装;

矢量图用graphics来实现;

位图直接new createjs.Bitmap(HResources.getResourceByTag("hexagon"));

创建按钮用HUtils.createBtn(HResources.getResourceByTag("buttons"),164,54,2,3);

(HUtils中的几个方法,参数具体含义看源文件)

动画用createjs.Sprite和createjs.SpriteSheet来实现,比较复杂,创建猫的时候再细说。

摆放完元件,让按钮侦听点击,点击之后发送相应的事件就完了。比如:

btn.addEventListener("click",clickHandler);
    function clickHandler(e){ 
    	var event = new createjs.Event("complete");
 		s.dispatchEvent(event);//类最开始有一个定义var s=this;
 		s.hide();
    }

修改完可以先预览一下效果,没有错误之后,在往下进行。

3)HGameLayer.js。

重头戏在这里。

对于神经猫游戏界面,主要有3层,最下层是背景,第二层是六边形,第3层是猫。

为了方便调整位置,我们在六边形和猫外边再套一层。

六边形的创建。

可以用位图来实现,也可以用矢量图,我用的位图。

六边形有两个状态,一个状态允许猫站上去,一个状态不允许猫站上去。因此应该有两个不同颜色的六边形图片。我们把图片放在了hexagon.png中。

//创建六边形
    function gethHexagon(){ 
    	var data = {
		images: [HResources.getResourceByTag("hexagon")],
		frames: {width:30, height:30,regX: 0, regY:0},
			animations: {
				normal:0,
				locked:1
			}
		};
		var spriteSheet = new createjs.SpriteSheet(data);
		var sp=new createjs.Sprite(spriteSheet,"normal");
		return sp;
    }

作者用的createjs.Sprite来创建六边形,createjs.Sprite相当于flash中的MovieClip,可以方便的用gotoAndStop()来跳转到不同的状态。

六边形只有两个状态,比较简单,也可以用自己用Bitmap来实现。

创建并摆放n*n个六边形就不多说了。

六边形的点击。

这个游戏,玩家的唯一操作就是点击六边形。

我们创建了n*n个六边形,如何侦听玩家点击呢。

由于六边形的矩形区域时重叠的,可能会使得侦听点击比较困难。

想到的解决办法:

(1)获取鼠标点击坐标,计算点击坐标在哪个六边形内。方法不太难,不会的话百度一下就有了。作者试了一下,由于用的六边形图片不是规则的六边形,导致精度略差。

(2)像素级别的判断。这里的六边形位置都是固定的,所以实现起来也简单,把六边形draw到一个bitmap上,每个六边形的颜色都不一样(与索引位置相关即可),点击的时候,获取bitmap相应位置的色值,根据色值即可判断点击的是哪个六边形。

最后是这么做的:直接侦听点击,判断target就行了。

这里需要注意:

(1)我们是给六边形的容器侦听点击,而不是六边形。因为容器加侦听,只需要一个就够了,六边形加侦听需要n*n,效率上会差很多。侦听处理里边取e.targe就可以取到六边形了。

(2)我们给六边形加了一个属性,用来存储六边形的二维索引位置。

初始化或者点击之后,切换六边形的状态,只需要gotoAndStop()就可以了。

猫的创建。

猫在逃跑时,有6个方向可以选择,考虑对称,也需要3个动画效果:左、左上、左下。可以看一下cat.png。

var anim01=[[0,0,31,45,0,13.75,35.25],[31,0,41,46,0,23.75,36.25],[72,0,40,63,0,23.75,36.25],[112,0,40,61,0,29.75,28.25],[152,0,40,61,0,29.75,28.25],[192,0,38,55,0,32.75,20.25],[0,63,38,55,0,32.75,20.25],[38,63,0,0,0,-0.25,-0.75]];
    var anim02=[[38,63,39,40,0,17.65,32.95],[77,63,44,40,0,20.65,32.95],[121,63,57,40,0,39.65,32.95],[178,63,54,39,0,48.65,31.950000000000003],[0,118,54,39,0,48.65,31.950000000000003],[54,118,56,35,0,53.65,26.950000000000003],[110,118,56,35,0,53.65,26.950000000000003],[166,118,0,0,0,-0.3500000000000014,-0.04999999999999716]];
	var anim03=[[166,118,30,46,0,13.899999999999999,35.25],[196,118,35,47,0,18.9,36.25],[0,165,42,62,0,23.9,53.25],[42,165,47,49,0,28.9,56.25],[89,165,47,49,0,28.9,56.25],[136,165,46,39,0,28.9,59.25],[182,165,46,39,0,28.9,59.25],[228,165,0,0,0,-0.10000000000000142,-0.75]];
	
	var n01=anim01.length;
	var n02=anim02.length+n01;
	var n03=anim03.length+n02;
	
	var data = {
		images: [HResources.getResourceByTag("cat")],
		frames:anim01.concat(anim02).concat(anim03),
		animations: {
			state01:[0,n01-1],
			state02:[n01,n02-1],
			state03:[n02,n03-1]
		}
	};
	var spriteSheet = new createjs.SpriteSheet(data);
	var sp= new createjs.Sprite(spriteSheet);

anim01、anim02、anim03对应3个动画,这3个数组是从flash中导出的。flash中,选中影片剪辑,生成sprite表,数据格式选择easeljs,会生成一个图片和一个js文件,js文件中有这个数组。

var spriteSheet = new createjs.SpriteSheet(data);

var sp= new createjs.Sprite(spriteSheet);

都比较简单,关键在于data的定义。可以多看看官方API中SpriteSheet的部分。frames数组以及图片可以借助其他工具生成,比如flash。

猫的动画播放。

猫跳的时候,需要播放相应的动画,动画播放结束之后,需要把猫恢复到初始的状态,并且移动到新的位置上。

如何才能知道动画播放结束呢?

flash中,我们是每一帧判断currentFrame是否等于totalFrames。createJs中提供了一个animationend事件,动画播放到最后一帧时,会发送animationend事件。

游戏逻辑。

游戏逻辑比较简单。

游戏初始化——>循环(用户点击——>猫跳一步)——>游戏结束

寻路算法

如果会Astar算法的话,这个就比较简单了,如果不会的话,先去学学Astar算法,网上有很多教程。

本次游戏中用到的寻路算法如下。

//寻路
	function getPath(){ 
		var startP=cat.p;

		var openTable=[];
		var tempTable=[];
		openTable.push(startP);
		var stepTable=[];
		for(i=0;i<WN;i++){ 
			stepTable[i]=[];
			for(j=0;j<HN;j++){ 
				stepTable[i][j]=0;
			}
		}
		var exitP;
		var canMove=false;
		var n=0;

		out:while(1){
			n++;
			while(1){ 
				var p=openTable.pop();
				if( !p){ 
					break;
				}
				var neighbor=p.j%2==0?NEIGHBOR_01:NEIGHBOR_02;
				for(i=0;i<6;i++){ 
					var ii=p.i+neighbor[i][0];
					var jj=p.j+neighbor[i][1];
					if(ii=WN||jj>=HN){ 
						continue;
					}
					if(ii==startP.i&&jj==startP.j){ 
						continue;
					}
					if(mapState[ii][jj]!=0){
						continue;
					}
					if(stepTable[ii][jj]){ 
						continue;
					}
					var p1={"i":ii,"j":jj,"parent":p};
					tempTable.push(p1);
					stepTable[ii][jj]=n;
					canMove=true;
					if(ii==0||jj==0||ii==WN-1||jj==HN-1){ 
						exitP=p1;
						break out;
					}
				}
			}
			if(tempTable.length==0){ 
				break;
			}
			openTable=tempTable;
			tempTable=[];
		}
		/*
		for(i=0;i<WN;i++){ 
			console.log(stepTable[i]);
		}
		*/
		if(!canMove){ //没有路了
			//console.log("没有路了");
			return null
		}
		if(!exitP){ //没有出口
			//console.log("没有出口");
			return {};
		}
		//console.log("出口位置:");console.log(exitP);
		var nextP=exitP;
		while(nextP.parent!=startP){ 
			nextP=nextP.parent;
		}
		return nextP;
	}

这个比Astar算法简单。

思路如下:

    猫的位置标0;

    相邻的位置(6个),可以跳过去的标1,

    和刚才标1的位置相邻的,并且没有检测过的位置标2;

    ……

    直到到达边界(找到出口),或者没有相邻的了(没有出路了)。

从出口位置往前倒,找到猫下一步的位置。让猫跳过去。

如果没有到达出口位置,并且猫的周围还有可以跳过去的位置,那么可以随便选个位置让猫跳过去。

判断结束

判断结束比较简单,猫到了最边上,游戏失败。猫周围没有位置可以跳过去,游戏成功。



在线演示

源码打包下载


« 上一篇下一篇 »

相关文章:

使用Typescript开发基于createjs的项目  (2016-8-25 9:54:40)

createjs中文API  (2016-8-18 8:45:24)

pixi和createjs效率对比  (2016-8-2 9:45:21)

createjs中stage.mouseX的bug  (2016-7-12 9:14:44)

createjs启用touch事件  (2016-7-12 9:7:5)

createjs指定文本最大高度  (2016-6-14 10:0:38)

使用libgdx开发Android游戏(转)  (2016-5-11 13:35:6)

密室逃生-animateCC版  (2016-4-26 11:45:49)

如何使用Createjs来编写HTML5游戏(转)  (2016-2-3 13:57:38)

createjs中Text中文不换行的问题(2)  (2015-11-25 10:58:11)

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。