前端技术   

[HTML5游戏开发]挑战横版ACT(一)

时间:2013-01-10 17:31:00

鄙人虽然不是专职的游戏开发者,但是自己也尝试着开发过各种各样类型的游戏,不过横版类游戏还没有尝试过,本次就使用lufylegend引擎来挑战一下横版ACT类游戏的开发,

大家可以到

http://lufylegend.com/lufylegend

下载lufylegend引擎的最新版本,

由于鄙人也是第一次开发此类游戏,所以有不妥的地方,欢迎大家回帖探讨和指正。

 

该系列文章目录(更新中)

(一):开天地黄忠初登场

http://blog.csdn.net/lufy_legend/article/details/8441677

(二):秀身手勇猛如当年

http://blog.csdn.net/lufy_legend/article/details/8476382

首先,素材问题,苦寻半个月,一直没找到满意的素材,不得已求助于黄忠黄老将军,黄老将军跟我说自从被马忠那个孙子暗算之后,已经有几百年没上战场了,一听说要上战场,立刻兴奋的不得了,直接就跳着《江南style》来了首《好汉歌》,那架势真有像是从梁山泊穿越而来的李逵,唱完后抄起家伙吼了声:“Go”,我也不敢怠慢,赶紧拿起电脑,准备起来。本次估且先拿黄老将军来挡一下,如果哪位朋友有好的素材,希望能提供一下,好让一把年纪的黄老将军休息一下。

由于黄老将军过于兴奋,只顾着一个劲儿的向前冲,所以只有向右的动作,没有向左的动作,为此我不得不使用lufylegend引擎中的LAnimation对象,因为LAnimation对象可以使用图片的镜像,来显示与上面的图片相反的动作。

考虑到战场上有各种各样的士兵武将,但是他们都属于人,有一些共通的属性,况且黄老将军过于兴奋,为了便于管理和操作,本次开发依然以OOP思想为基础(黄老将军听了后自言自语道,哦哦屁?),先来建一个人物的父类Character

 

[javascript] view plaincopy
  1. function Character(dataList,coordinateList,locationList,speed){  
  2.     base(this,LSprite,[]);  
  3. };  

来看看这四个参数:

dataList:举个例子,看上面黄老将军的图片,有很多组动作,每组动作为一张图片,参数dataList就是这几组图片

coordinateList:LAnimation对象需要根据坐标来顺序显示图片,以形成动画,这个即使要传入LAnimation对象的坐标数组

locationList:考虑到人物的每个动作的图片的大小都不一样,位置也不一样,这个数组用来调整相对应动作组图片的显示位置

speed:方便控制人物动作在时间轴上每帧的频率

下面是Character类的完整构造器

 

[javascript] view plaincopy
  1. function Character(dataList,coordinateList,locationList,speed){  
  2.     base(this,LSprite,[]);  
  3.     var self = this;  
  4.     //初始化  
  5.     //动作  
  6.     self.action = ACTION.STAND;  
  7.     //方向  
  8.     self.direction = DIRECTION.RIGHT;  
  9.     //保存参数  
  10.     self.coordinateList = coordinateList;  
  11.     self.locationList = locationList;  
  12.     self.dataList = dataList;  
  13.     self.speed = speed==null?1:speed;  
  14.     //保存初始化动作的图片  
  15.     self.data = dataList[ACTION.STAND];  
  16.     self.speedIndex = 0;  
  17.     //利用LAnimation对象来显示连贯的动作  
  18.     self.anime = new LAnimation(self,self.data,self.coordinateList[0]);  
  19.     self.anime.setAction(0);  
  20.     self.anime.x = -self.data.width*0.5;  
  21.     self.anime.y = -self.data.height;  
  22. };  

其中ACTION变量和DIRECTION变量为别如下

 

[javascript] view plaincopy
  1. //动作  
  2. var ACTION = {STAND:0,MOVE:1,RUN:2,JUMP:3,ATTACK:4};  
  3. //方向  
  4. var DIRECTION = {RIGHT:"right",LEFT:"left"};  

 

下面详细介绍下LAnimation类,LAnimation类是通过顺序或倒序播放一组图片来形成动画,它的官方解释如下

LAnimation类 LAnimation(layer,data,list)

■作用:
实现简单动画的播放,原理是将一张大的图片,按照保存有坐标的二维数组保存的坐标来逐个显示。
■参数:
layer:LSprite显示层
data:LBitmapData对象
list:装有坐标的二维数组

上面的三个参数中,layer是一个LSprite对象,data是一个LBitmapData对象,这些都比较好理解,第三个参数list是一个二维数组,它的格式如下

 

[javascript] view plaincopy
  1. [  
  2. [{x:0,y:0},{x:0,y:0},{x:0,y:0}],  
  3. [{x:0,y:0},{x:0,y:0},{x:0,y:0}],  
  4. [{x:0,y:0},{x:0,y:0},{x:0,y:0}]  
  5. ]  
LAnimation对象的setAction函数,有四个参数,分别为
[javascript] view plaincopy
  1. LAnimation.setAction(rowIndex,colIndex,mode,isMirror)  
  2. 参数:  
  3. rowIndex:播放动画的行号  
  4. colIndex:播放动画的列号  
  5. mode:(1,0,-1)分别代表(正序播放,静止,倒序播放)  
  6. isMirror:Boolean型,当设定为true的时候,图片显示为水平翻转后的镜像  
当然,光有一个构造器是不行的,因为LAnimation对象是通过调用onframe函数来实现播放的,所以给Character类添加一个函数,如下

 

 

[javascript] view plaincopy
  1. Character.prototype.onframe = function (){  
  2.     var self = this;  
  3.     //人物动作速度控制  
  4.     if(self.speedIndex++ < self.speed)return;  
  5.     self.speedIndex = 0;  
  6.     //人物动画播放  
  7.     self.anime.onframe();  
  8. };  
如此一来,只要不断的调用Character的实例的onframe函数,就能实现动态播放了。

 

黄老将军可能对比不感兴趣,此时已经在一旁打起了呼噜,我必须加快速度了......

考虑到战场上敌方和我方会有不同处理,建立一个继承自Character类的子类,如下

 

[javascript] view plaincopy
  1. function Player(datalist,coordinateList,locationList,speed){  
  2.     base(this,Character,[datalist,coordinateList,locationList,speed]);  
  3. };  
因为想要实例化这个类,需要三个参数,我再新建一个对象来获取这三个参数

 

 

[javascript] view plaincopy
  1. var CharacterList = {  
  2.     huangzhong:function(){  
  3.         //图片数据  
  4.         var dataList = new Array();  
  5.         dataList.push(new LBitmapData(imglist["player_stand"],0,0,106,77));  
  6.         dataList.push(new LBitmapData(imglist["player_move"],0,0,115,85));  
  7.         dataList.push(new LBitmapData(imglist["player_run"],0,0,125,87));  
  8.         dataList.push(new LBitmapData(imglist["player_jump"],0,0,131,212));  
  9.         dataList.push(new LBitmapData(imglist["player_attack"],0,0,242,143));  
  10.         //图片分割数据  
  11.         var coordinateList = new Array();  
  12.         coordinateList.push(LGlobal.divideCoordinate(1272,77,1,12));  
  13.         coordinateList.push(LGlobal.divideCoordinate(920,85,1,8));  
  14.         coordinateList.push(LGlobal.divideCoordinate(750,87,1,6));  
  15.         coordinateList.push(LGlobal.divideCoordinate(786,212,1,6));  
  16.         var attackList = LGlobal.divideCoordinate(484,143,1,2);  
  17.         coordinateList.push([[attackList[0][0],attackList[0][1],attackList[0][1],attackList[0][1]]]);  
  18.         //图片位置数据  
  19.         var locationList = new Array();  
  20.         locationList.push({x:0,y:0});  
  21.         locationList.push({x:0,y:0});  
  22.         locationList.push({x:0,y:0});  
  23.         locationList.push({x:0,y:0});  
  24.         locationList.push({x:20,y:20});  
  25.         return [dataList,coordinateList,locationList];  
  26.     }  
  27. }  
所以我们要得到黄老将军的参数的话,就直接CharacterList.huangzhong()就可以了。

 

这时候,耳旁突然一声大吼,用什么拼音,要用English,怎么的也得叫Mr.Huang或者Huang Sir吧,由于英语太差,所以我假装没听到,继续写代码......
下面,开始就马上开始游戏初始化的工作。

 

[javascript] view plaincopy
  1. //初始化层  
  2. baseLayer = new LSprite();  
  3. addChild(baseLayer);  
  4.       
  5. //背景层  
  6. backLayer = new LSprite();  
  7. backLayer.graphics.drawRect(1,"#000",[0,0,LGlobal.width,LGlobal.height],true,"#000");  
  8. baseLayer.addChild(backLayer);  
  9.       
  10. //人物层  
  11. charaLayer = new LSprite();   
  12. baseLayer.addChild(charaLayer);  
  13. addHero();  
  14.   
  15. //添加贞事件  
  16. baseLayer.addEventListener(LEvent.ENTER_FRAME,onframe);  
暂时没有准备背景图片,所以就画了一个黑色矩形当做背景了,下面看addHero函数和onframe函数

 

 

[javascript] view plaincopy
  1. function addHero(){  
  2.     var heroData = CharacterList.huangzhong();  
  3.     hero = new Player(heroData[0],heroData[1],heroData[2]);  
  4.     hero.x = 200;  
  5.     hero.y = 200;  
  6.     charaLayer.addChild(hero);  
  7. }  
  8. function onframe(){  
  9.     var key = null;  
  10.     for(key in charaLayer.childList){  
  11.         charaLayer.childList[key].onframe();  
  12.     }  
  13. }  
运行代码,得到效果如下

 


话说,黄老将军正在呼呼地睡大觉,突然被我弄进了游戏里,并且四种漆黑一片,立刻就想到跑,但是由于我没有添加动作变换代码,它只能傻傻的站在那里,脑子里各种问号,为了不欺负人家,我必须赶紧写下去。

游戏中,有走,跑,跳,攻击等各种动作,咱们就用键盘的wsad来控制上下左右,j控制攻击,k控制跳,首先要添加键盘事件

[javascript] view plaincopy
  1. //添加键盘事件  
  2. LEvent.addEventListener(LGlobal.window,LKeyboardEvent.KEY_DOWN,onkeydown);  
  3. LEvent.addEventListener(LGlobal.window,LKeyboardEvent.KEY_UP,onkeyup);  
[javascript] view plaincopy
  1. function onkeydown(e){  
  2.     if(keylock)return;  
  3.     switch(e.keyCode){  
  4.         case KEY.LEFT:  
  5.             hero.setAction(ACTION.MOVE,DIRECTION.LEFT);  
  6.             break;  
  7.         case KEY.RIGHT:  
  8.             hero.setAction(ACTION.MOVE,DIRECTION.RIGHT);  
  9.             break;  
  10.         case KEY.UP:  
  11.             hero.setAction(ACTION.MOVE,hero.direction);  
  12.             break;  
  13.         case KEY.DOWN:  
  14.             hero.setAction(ACTION.MOVE,hero.direction);  
  15.             break;  
  16.         case KEY.ATTACK: 
  17.             keylock = true;  
  18.             hero.setAction(ACTION.ATTACK,hero.direction);  
  19.             break;  
  20.         case KEY.JUMP:  
  21.             keylock = true;  
  22.             hero.setAction(ACTION.JUMP,hero.direction);  
  23.             break;  
  24.     }  
  25. }  
  26. function onkeyup(e){  
  27.     if(hero.action == ACTION.MOVE || hero.action == ACTION.RUN)hero.setAction(ACTION.STAND,hero.direction);  
  28.     keylock = false;  
  29. }  
hero是Player对象的一个实例,既然调用了Player对象的setAction函数,那就必须给Player对象添加这个函数,不过我依然将函数添加到它的父类Character里面

 

 

[javascript] view plaincopy
  1. /** 
  2.  * 动作变换 
  3.  * @param action 动作 
  4.  * @param direction 方向 
  5.  */  
  6. Character.prototype.setAction = function (action,direction){  
  7.     var self = this;  
  8.     //动作和方向都没有改变,则不做变换  
  9.     if(self.action == action && self.direction == direction)return;  
  10.     //重新设定保存在LAnimation对象中的图片和坐标数组  
  11.     self.data = self.dataList[action];  
  12.     self.anime.bitmap.bitmapData = self.data;  
  13.     self.anime.bitmap.bitmapData.setCoordinate(0,0);  
  14.     self.anime.imageArray = self.coordinateList[action];  
  15.     self.action = action;  
  16.     self.direction = direction;  
  17.     //如果方向向左则必须使用镜像  
  18.     self.anime.setAction(0,0,null,self.direction == DIRECTION.LEFT);  
  19.     //调整位置  
  20.     self.setLocation();  
  21.     //如果被添加了事件,则将事件移除  
  22.     self.anime.removeEventListener(LEvent.COMPLETE,self.overAction);  
  23.     //除了走和跑,其他动作要保持连贯性,在一个动作结束之前,不能再次变换,所以添加动画播放结束事件,来控制keylock的值  
  24.     if(self.action != ACTION.MOVE && self.action != ACTION.RUN){  
  25.         self.anime.addEventListener(LEvent.COMPLETE,self.overAction);  
  26.     }  
  27. };  
  28. Character.prototype.setLocation = function (){  
  29.     var self = this;  
  30.     self.anime.x = self.locationList[self.action].x*(self.direction == DIRECTION.LEFT ? -1 : 1)-self.data.width*0.5;  
  31.     self.anime.y = self.locationList[self.action].y-self.data.height;  
  32. };  
  33. Character.prototype.overAction = function (anime){  
  34.     var self = anime.parent;  
  35.     self.anime.removeEventListener(LEvent.COMPLETE,self.overAction);  
  36.     self.setAction(ACTION.STAND,self.direction);  
  37.     keylock = false;  
  38. };  
也许是黄老将军太久没有上战场了,现在已经开始活蹦乱跳了

 

测试连接

http://lufy.netne.net/lufylegend-js/act/index.html


 

黄老将军虽然无比兴奋,但是很快就发现了不对劲儿,因为无论走,跳,向左,向右,他只能在同一个地方折腾,急得他满头大汗,于是我在他回头看我之前,我就先闪人了,身后传来黄老将军的一声怒吼:“我X”。

本次丫丫就到这里了,要想知道黄老将军在战场上究竟做了什么,请听下回分析。

本次源码下载

http://fsanguo.comoj.com/download.php?i=act01.rar

 

转载请注明:转自lufy_legend的博客

欢迎继续关注我的博客

 

来源:PHPchina

上一篇:顶尖CSS Web设计师Andy Clarke访谈 2013-01-11

下一篇:快速构建实时抓取集群 2013-01-10

Notice: Constant RUNTIME already defined in /srv/html/srccn/news/config.php on line 15 Notice: Constant ROOTDIR already defined in /srv/html/srccn/news/config.php on line 16 Notice: Constant SITEDIR already defined in /srv/html/srccn/news/config.php on line 17 Notice: Constant DATAURL already defined in /srv/html/srccn/news/config.php on line 20 Notice: Constant VERSION already defined in /srv/html/srccn/news/system/kernel.php on line 17 Notice: Constant COREDIR already defined in /srv/html/srccn/news/system/kernel.php on line 18 Fatal error: require(): Cannot redeclare class mysql in /srv/html/srccn/news/system/kernel.php on line 22