[HTML5游戏开发]挑战横版ACT(二):秀身手勇猛如当年

本篇是该系列文章第二篇,其他文章请看下面帖子中的目录

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

话说突然想起来黄忠黄老将军被我仍在漆黑的战场上已经有一段时日了,没吃没喝的,不知道怎么样了。
等我来到战场上一看,才发现这个担心是多余的,老将军依然精神抖擞的在原地活蹦乱跳,嘴里不停的喊着,“别想困住老夫,老夫已经死过一回了”。

看着老将军如此拼命的想要往前走两步,我决定让老将军走动起来。
不过首先,得先让战场明亮起来,准备一张背景图片,然后使用LBitmap对象显示到游戏中,并将原来的黑色矩形注释掉。

//背景层
	backLayer = new LSprite();
	//backLayer.graphics.drawRect(1,"#000",[0,0,LGlobal.width,LGlobal.height],true,"#000");
	baseLayer.addChild(backLayer);
	var background = new LBitmap(new LBitmapData(imglist["back"]));
	backLayer.addChild(background);
效果如下


黄老将军看了看久违的熟悉的战场,又看了看战场上的“董”字旗子,吼道:“差点没气晕过去,董卓跟老夫有哪门子关系啊!?”

其实我也没办法,没有找到合适的图片了,下面就是让人物动起来了,黄忠在旁边继续吼到:“早就已经动起来了,只是不能动地方而已,都快累死了。”。话说这老家伙火怎么这么大...

懒得理他,继续写代码,下面将前面的代码休整一下,一个动作一个动作来。我只写核心部分,完整代码一会儿给出下载。

1,走动

游戏中,键盘的各个键的状态是按下还是弹起,是需要准确判断的,所以准备一个keyCtrl数组,来保存键盘键的状态。

在按下的时候,使用

keyCtrl[e.keyCode] = true;
在弹起的时候,使用

keyCtrl[e.keyCode] = false;
这样,每个键的状态,就可以通过keyCtrl数组来获取。

接着,在Character类的onframe函数中调用move函数,在move函数中根据人物当前的状态,计算移动的步长,来进行移动。

Character.prototype.move = function (){
	var self = this, mx = self.mx, my = self.my;
	if(self.action == ACTION.MOVE || self.action == ACTION.JUMP || self.action == ACTION.JUMP_ATTACK){
		mx *= MOVE_STEP;
		my *= MOVE_STEP;
	}else if(self.action == ACTION.RUN){
		mx *= MOVE_STEP*2;
		my *= MOVE_STEP*2;
	}else if(self.action == ACTION.HIT){
		mx = MOVE_STEP*2*(self.direction == DIRECTION.RIGHT ? 1 : -1);
		my = 0;
	}else{
		mx = my = 0;
	}
	if(mx == 0 && my == 0)return;
	self.x += mx;
	self.y += my;
	if(self.y < 250){
		self.y = 250;
	}else if(self.y > 448){
		self.y = 448;
	}
};
上面的self.mx,self.my在Player类中进行计算

Player.prototype.move = function (){
	var self = this, mx = 0, my = 0;
	if(keyCtrl[KEY.LEFT]){
		mx = -1;
	}else if(keyCtrl[KEY.RIGHT]){
		mx = 1;
	}else if(keyCtrl[KEY.UP]){
		my = -1;
	}else if(keyCtrl[KEY.DOWN]){
		my = 1;
	}
	self.mx = mx;
	self.my = my;
	self.callParent("move",arguments);
};
callParent函数是lufylegend引擎中调取父类函数的方法,两个参数,第一个参数是父类的方法名,第二个参数是固定参数arguments,因为Player继承自Character,所以就是调用Character对象的move函数。

然后在键盘键按下的侦听函数onkeydown中根据按键来改变人物的状态,就能实现了人物的行走了。

2,跑动

跑动就是连续按两下左或者右,这就需要判断上一次和这一次两次的按键,考虑到后面的绝招等,这里建立一个储存按键的数组keyList

var keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}];

每次按键,都将当前的信息压入该数组,然后将不需要的按键信息(两次以前)移除。

var keyThis = {keyCode:e.keyCode,time:(new Date()).getTime()};
var keyLast01 = keyList[0];
var keyLast02 = keyList[1];
keyList.unshift(keyThis);
keyList.pop();

然后,根据按键序列中的信息,进行判断,是否进行跑动

	switch(e.keyCode){
		case KEY.LEFT:
			if(keyLast01.keyCode == KEY.LEFT && keyThis.time - keyLast01.time < 200){
				hero.setAction(ACTION.RUN,DIRECTION.LEFT);
			}else{
				hero.setAction(ACTION.MOVE,DIRECTION.LEFT);
			}
			break;
		case KEY.RIGHT:
			if(keyLast01.keyCode == KEY.RIGHT && keyThis.time - keyLast01.time < 200){
				hero.setAction(ACTION.RUN,DIRECTION.RIGHT);
			}else{
				hero.setAction(ACTION.MOVE,DIRECTION.RIGHT);
			}
			break;

3,跳跃

了便于控制,我将跳跃图片修改了一下


因为人物动作是通过LAnimation对象来显示的,所以只要在跳跃的过程中,改变LAnimation对象的y坐标,就能实现跳跃了

我在Player类中对onframe函数进行了重写

Player.prototype.onframe = function (){
	var self = this;
	self.callParent("onframe",arguments);
	if(self.action == ACTION.JUMP){
		self.onjump();
	}else if(self.action == ACTION.JUMP_ATTACK){
		self.onjump_attack();
	}
};
上面代码,当人物跳跃或者跳跃攻击的时候,会调用相应的onjump函数和onjump_attack函数,在这两个函数内根据图片的播放序号,来修改LAnimation对象的y坐标

Player.prototype.onjump = function (){
	var self = this;
	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];
};
Player.prototype.onjump_attack = function (){
	var self = this;
	self.setLocation();
	var index = self.anime.colIndex;
	if(index >= self.yArr.length)return;
	self.anime.y += self.yArr[index];
};
这样,跳跃就完美实现了。

4,攻击

攻击的时候,在攻击动作结束之前,不可能进行走动或者跳跃等其他动作的,所以在攻击键按下的时候,需要将按键上锁,让按键无效

setTimeout("keylock = true;",50);
hero.setAction(ACTION.ATTACK,hero.direction);
为什么要使用setTimeout函数?,因为还有绝招的发动,绝招的发动需要攻击键和跳跃键同时按下,但是人不可能同时按下两个键的,要有一个很小的间隔,我这里将这个间隔的最大值设定为50毫秒,所以在这50毫秒以内,是可以再按下跳跃键的。

5,连续攻击

当连续几次普通攻击的时候,是会出现一次特殊的攻击的,我设定每三次攻击,进行一次特殊攻击

case KEY.ATTACK:
if(keyLast01.keyCode == KEY.ATTACK && keyLast02.keyCode == KEY.ATTACK && keyThis.time - keyLast02.time < 1000){
	keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}];
	keylock = true;
	hero.setAction(ACTION.BIG_ATTACK,hero.direction);
}
当然,需要判断一下这几次连续攻击的时间,这里设定在1秒钟内进行三次攻击,则判定为连续攻击。

6,跳跃攻击

这个也简单,只要在人物处于跳跃状态的时候进行攻击,则判定为跳跃攻击。

case KEY.ATTACK:
	if(keyLast01.keyCode == KEY.ATTACK && keyLast02.keyCode == KEY.ATTACK && keyThis.time - keyLast02.time < 1000){
		keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}];
		keylock = true;
		hero.setAction(ACTION.BIG_ATTACK,hero.direction);
	}else if(hero.action == ACTION.JUMP){
		hero.setAction(ACTION.JUMP_ATTACK,hero.direction);
	}else{
		setTimeout("keylock = true;",50);
		hero.setAction(ACTION.ATTACK,hero.direction);
	}

7,技能攻击

玩过街机三国志的朋友们都知道,下=>上=>攻击,就会发动一下特殊的武将技,这个也简单,在攻击键按下的时候判断一下前两次按键就可以了。

if(keyLast01.keyCode == KEY.UP && keyLast02.keyCode == KEY.DOWN && keyThis.time - keyLast02.time < 300){
	keylock = true;
	hero.setAction(ACTION.SKILL,hero.direction);
}

8,大绝招

当满屏幕的敌人围住自己的时候,怎么办?放大招呗。

在攻击键按下的时候,判断一下跳跃键是不是同时被按下了。

if(keyLast01.keyCode == KEY.JUMP && keyThis.time - keyLast01.time < 50){
	keylock = true;
	hero.setAction(ACTION.BIG_SKILL,hero.direction);
}
当然,在跳跃键按下的时候,也需要判断一下攻击键是不是被按下了。

if(keyLast01.keyCode == KEY.ATTACK && keyThis.time - keyLast01.time < 50){
	keylock = true;
	hero.setAction(ACTION.BIG_SKILL,hero.direction);
}
绝招发动的时候,其他按键是无效的,所以键按键上锁keylock=true;

比较特殊的是,绝招图片的动作比较多,全都合到一行上的话,图片太长,所以我分成了5行。

其他的动作图片都是一行,所以这里需要做些特殊处理,就是当一行图片播放完之后,马上开始播放下一行图片,知道全部动作都播放完为止。

处理过程是,首先在动作改变的时候,加上侦听函数

self.anime.addEventListener(LEvent.COMPLETE,self.overAction);
这样,当一组动作播放完毕之后,会调用overAction函数

下面是Character对象的overAction函数

Character.prototype.overAction = function (anime){
	var self = anime.parent;
	self.anime.removeEventListener(LEvent.COMPLETE,self.overAction);
	var lastAction = self.action;
	var animeAction = anime.getAction();
	self.setAction(ACTION.STAND,self.direction);
	self.overActionRun(lastAction,animeAction);
};
Character.prototype.overActionRun = function (lastAction,animeAction){
};
LAnimation对象的getAction函数是获取当前的属性,包括播放的图片序号和镜像等,具体请参照lufylegend引擎的API文档,接着在Player对象中重写overActionRun函数。

Player.prototype.overActionRun = function (lastAction,animeAction){
	var self = this;
	self.callParent("overActionRun",arguments);
	keylock = false;
	
	if(lastAction == ACTION.BIG_SKILL && animeAction[0] < 3){
		keylock = true;
		self.setAction(ACTION.BIG_SKILL,self.direction);
		self.anime.setAction(animeAction[0]+1);
		self.anime.onframe();
	}
};
animeAction[0]是播放图片的行序号,根据行序号的值,判定是否继续播放下一行动作,绝招处理完成。


最后,整合一下上面的处理,onkeydown函数的完整代码如下。

function onkeydown(e){
	if(keylock || keyCtrl[e.keyCode])return;
	
	var keyThis = {keyCode:e.keyCode,time:(new Date()).getTime()};
	var keyLast01 = keyList[0];
	var keyLast02 = keyList[1];
	
	keyCtrl[e.keyCode] = true;
	keyList.unshift(keyThis);
	keyList.pop();
	
	switch(e.keyCode){
		case KEY.LEFT:
			if(keyLast01.keyCode == KEY.LEFT && keyThis.time - keyLast01.time < 200){
				hero.setAction(ACTION.RUN,DIRECTION.LEFT);
			}else{
				hero.setAction(ACTION.MOVE,DIRECTION.LEFT);
			}
			break;
		case KEY.RIGHT:
			if(keyLast01.keyCode == KEY.RIGHT && keyThis.time - keyLast01.time < 200){
				hero.setAction(ACTION.RUN,DIRECTION.RIGHT);
			}else{
				hero.setAction(ACTION.MOVE,DIRECTION.RIGHT);
			}
			break;
		case KEY.UP:
			hero.setAction(ACTION.MOVE,hero.direction);
			break;
		case KEY.DOWN:
			hero.setAction(ACTION.MOVE,hero.direction);
			break;
		case KEY.ATTACK:
			if(keyLast01.keyCode == KEY.ATTACK && keyLast02.keyCode == KEY.ATTACK && keyThis.time - keyLast02.time < 1000){
				keyList = [{keyCode:0,time:0},{keyCode:0,time:0},{keyCode:0,time:0}];
				keylock = true;
				hero.setAction(ACTION.BIG_ATTACK,hero.direction);
			}else if(keyLast01.keyCode == KEY.JUMP && keyThis.time - keyLast01.time < 50){
				keylock = true;
				hero.setAction(ACTION.BIG_SKILL,hero.direction);
			}else if(hero.action == ACTION.JUMP){
				hero.setAction(ACTION.JUMP_ATTACK,hero.direction);
			}else if(keyLast01.keyCode == KEY.UP && keyLast02.keyCode == KEY.DOWN && keyThis.time - keyLast02.time < 300){
				keylock = true;
				hero.setAction(ACTION.SKILL,hero.direction);
			}else{
				setTimeout("keylock = true;",50);
				hero.setAction(ACTION.ATTACK,hero.direction);
			}
			break;
		case KEY.JUMP:
			if(keyLast01.keyCode == KEY.ATTACK && keyThis.time - keyLast01.time < 50){
				keylock = true;
				hero.setAction(ACTION.BIG_SKILL,hero.direction);
			}else if(keyCtrl[KEY.DOWN]){
				hero.setAction(ACTION.HIT,hero.direction);
			}else{
				hero.setAction(ACTION.JUMP,hero.direction);
			}
			break;
	}
}




测试连接如下:

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

下面是各个动作的按键,大家可以测试一下

走动:A向左,D向右,W向上,S向下


跑:按两下走动


跳:K


攻击:J


连续攻击:攻击多次


跳跃攻击:K => J


撞击:S+K


技能攻击:S => W => J


绝招:J+K



老将军既然已经能跑能跳了,便冲着我大喊:“马忠在哪儿?”。要知道找个素材那可是比登天还难啊,我上哪里给他找马忠去啊,下次还是先给他整几个炮灰让他先过过瘾吧。

上面说的可能有点乱,现在给出本次源码下载,喜欢的可以看一下。

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

注意:该附件只包含本次文章源码,lufylegend.js引擎请到http://lufylegend.com/lufylegend进行下载。

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

欢迎继续关注我的博客

http://blog.csdn.net/lufy_legend



评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值