本篇是该系列文章第三篇,其他文章请看下面帖子中的目录
http:///html5-tutorial-354344.html
开篇啰嗦
本系列教程,是我首次采用调侃式开发,文中大多数内容都是口水,大家直接空干了读就行了,谨防被淹。
进行该类型开发的第一个瓶颈,就是素材了,在此多谢网友yorhomwang提供了大量素材网址。
下面是本次开发的成果,大家先预览一下。
素材转换工具
本次找到的素材都是gif类型的图片,想要在游戏里使用,需要将gif图片的每一帧动作取出来组成一张新的图片,我用flash制作了一个简单的转换工具,有需要的朋友请直接拿去用就行了,网址如下。
http://lufylegend.com/flash/demo/GifToPng
正题
可以说,黄老将军已经被我凉在战场上有一段日子了,这些天已经无聊到了极点,拿着刀在战场了发疯似得砍着,跑着,咆哮着......
我是在不忍心看下去了,决心继续写几行代码,给他老人家添点乐趣。
一,战场移动
首先,先让战场的地图移动起来,总不能怎么跑都在一个地方吧,定义一个变量。
var back_run = true;
当这个变量为true的时候,战场的背景地图是可以移动的,否则不可移动。
接着在Player.js的move函数里添加控制战场移动的代码,为什么在Player.js里,而不是在Character.js里呢?因为只有主人公黄老将军移动的时候,地图才会移动嘛,Character是父类,待会敌人也会继承自这个类。
Player.prototype.move = function (){ var self = this, mx = 0, my = 0; if(keyCtrl[KEY.LEFT] && charaLayer.x + self.x > 0){ mx = -1; }else if(keyCtrl[KEY.RIGHT] && charaLayer.x + self.x < LGlobal.width){ mx = 1; } if(keyCtrl[KEY.UP]){ my = -1; }else if(keyCtrl[KEY.DOWN]){ my = 1; } self.mx = mx; self.my = my; if(self.action == ACTION.RUN){ mx *= 2; my *= 2; }else if(self.action == ACTION.HIT){ mx = 2*(self.direction == DIRECTION.RIGHT ? 1 : -1); my = 0; } if(back_run && mx > 0 && charaLayer.x + self.x > LGlobal.width * 0.5){ var setX = mx*MOVE_STEP; if(backLayer.data.x + setX + backLayer.data.width > backLayer.data.image.width){ back_run = false; setX = backLayer.data.image.width - backLayer.data.width - backLayer.data.x; } charaLayer.x -= setX; backLayer.data.setCoordinate(backLayer.data.x + setX,backLayer.data.y); addEnemy(); } self.callParent("move",arguments); };
可以看到,当主人公移动的时候,地图坐标会向相反的方向增减,这样就实现了视觉上的地图移动,注意,里面有一行调用了addEnemy函数,这个函数是检测是否往战场上添加一个敌人。
二,增加敌人
下面看看怎么来添加一个敌人,我找到了孙尚香的几个素材,这个素材比较全,下面是其中的一张,不一一列出了。
下面增设一个Enemy.js类
function Enemy(list,speed){ var self = this; base(this,Character,[list,speed]); self.belong = "enemy"; self.hp = 100; }; Enemy.prototype.onjump = function (){ var self = this; self.callParent("onjump",arguments); self.setLocation(); var index = self.anime.colIndex; self.yArr = [0,-10,-20,-30,-40,-40,-30,-20,-10,0]; self.anime.y += self.yArr[index]; }; Enemy.prototype.onjump_attack = function (){ var self = this; self.callParent("onjump_attack",arguments); self.setLocation(); var index = self.anime.colIndex; if(index >= self.yArr.length)return; self.anime.y += self.yArr[index]; }; Enemy.prototype.setAction = function (action,direction){ var self = this,yArr = new Array(); if(action == ACTION.MOVE && self.action == ACTION.JUMP)return; if(action == ACTION.JUMP_ATTACK){ var index = self.anime.colIndex,i; for(i = index;i0){ self.anime.y += self.yArr[0]; } }; Enemy.prototype.overActionRun = function (lastAction,animeAction){ var self = this; self.callParent("overActionRun",arguments); keylock = false; if(lastAction == ACTION.FALL){ if(self.direction == DIRECTION.LEFT){ self.x += 80; }else{ self.x -= 80; } } }; Enemy.prototype.move = function (){ var self = this, mx = 0, my = 0; self.mx = mx; self.my = my; self.callParent("move",arguments); };
这个类和Player.js是类似的,都继承自Character类,只是构造器我不在把每一个相关的数组传进去了,太麻烦了,而是传了一个数组list,里面有需要设定的所有参数。
当添加敌人的addEnemy()函数被调用的时候,我们不可能无限制的添加敌人,所以提前准备好,要添加的敌人,和什么时候添加。
var enemy_list = new Array( {name:"sunji",x:800,y:350,when_x:300,back_run:false}, {name:"huangzhong",x:1200,y:280,when_x:800,back_run:true} ); function addEnemy(){ if(enemy_list.length == 0)return; if(enemy_list[0].when_x > hero.x)return; var charadata = CharacterList[enemy_list[0].name](); var enemy = new Enemy(charadata); enemy.x = enemy_list[0].x; enemy.y = enemy_list[0].y; charaLayer.addChild(enemy); enemy_list.shift(); }
我添加了一个enemy_list数组,它里面包含了什么时候添加敌人的when_x,和敌人出现的位置坐标,还有该人物出现后,地图是否停止移动等信息,当addEnemy函数被调用的时候,就通过when_x和主人公的位置来判断是否需要添加该敌人。
三,攻击
有了敌人,就要有战斗了,下面来说一说攻击与被攻击的判定。
攻击的判定,其实就是碰撞的检测,当然我们可以使用像素级碰撞,但是对于此类游戏来说,就有点大题小做了,而且效率实在太低,所以这里采用矩形碰撞的检测。
lufylegend.js引擎中有LGlobal.hitTest()函数,可以用来检测矩形是否发生碰撞,但是由于图片素材中有很多空白区域,直接采用此方法的话,误差有点太大了,所以我提前为人物的每一帧设定好需要检测的攻击范围和被攻击范围,看下面的CharacterList.js中的代码。
var CharacterList = { huangzhong:function(){ //图片数据 var dataList = new Array(); dataList.push(new LBitmapData(imglist["player_stand"],0,0,106,77)); dataList.push(new LBitmapData(imglist["player_move"],0,0,115,85)); dataList.push(new LBitmapData(imglist["player_run"],0,0,125,87)); dataList.push(new LBitmapData(imglist["player_jump"],0,0,131,134)); dataList.push(new LBitmapData(imglist["player_attack"],0,0,242,143)); dataList.push(new LBitmapData(imglist["player_big_attack"],0,0,232,143)); dataList.push(new LBitmapData(imglist["player_jump_attack"],0,0,232,143)); dataList.push(new LBitmapData(imglist["player_hit"],0,0,161,88)); dataList.push(new LBitmapData(imglist["player_skill"],0,0,324,140)); dataList.push(new LBitmapData(imglist["player_big_skill"],0,0,441,166)); dataList.push(new LBitmapData(imglist["player_hert"],0,0,179,87)); dataList.push(new LBitmapData(imglist["player_fall"],0,0,298,157)); //图片分割数据 var coordinateList = new Array(); coordinateList.push(LGlobal.pideCoordinate(1272,77,1,12)); coordinateList.push(LGlobal.pideCoordinate(920,85,1,8)); coordinateList.push(LGlobal.pideCoordinate(750,87,1,6)); var jumpList = LGlobal.pideCoordinate(655,134,1,5); coordinateList.push([[jumpList[0][0],jumpList[0][0],jumpList[0][1],jumpList[0][1],jumpList[0][2],jumpList[0][2],jumpList[0][3],jumpList[0][3],jumpList[0][4],jumpList[0][4]]]); var attackList = LGlobal.pideCoordinate(484,143,1,2); coordinateList.push([[attackList[0][0],attackList[0][1],attackList[0][1],attackList[0][1]]]); var bigattackList = LGlobal.pideCoordinate(927,143,1,4); coordinateList.push(bigattackList); var jumpattackList = LGlobal.pideCoordinate(927,143,1,4); coordinateList.push(jumpattackList); coordinateList.push(LGlobal