本篇是本系列文章第二篇,其他文章請看下面文章中的目錄
http://www.php.cn/ html5-tutorial-354344.html
話說突然想起來黃忠黃老將軍被我仍在漆黑的戰場上已經有一段時日了,沒吃沒喝的,不知道怎麼樣了。
等我來到戰場上一看,才發現這個擔心是多餘的,老將軍依然精神抖擻的在原地活蹦亂跳,嘴裡不停的喊著,「別想困住老夫,老夫已經死過一回了」。
看著老將軍如此拼命的想要往前走兩步,我決定讓老將軍走動起來。
不過首先,得先讓戰場明亮起來,準備一張背景圖片,然後使用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);
效果如下
#黃老將軍看了看久違的熟悉的戰場,又看了看戰場上的「董」字旗子,吼道:「差點沒氣暈過去,董卓跟老夫有哪門子關係啊!?」
其實我也沒辦法,沒有找到合適的圖片了,下面就是讓人物動起來了,黃忠在旁邊繼續吼到:「早就已經動起來了,只是不能動地方而已,都快累死了。」。話說這老傢伙火怎麼這麼大...
懶得理他,繼續寫程式碼,下面將前面的程式碼休整一下,一個動作一個動作來。我只寫核心部分,完整程式碼一會兒給下載。
遊戲中,鍵盤的各個鍵的狀態是按下還是彈起,是需要準確判斷的,所以準備一個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中根據按鍵來改變人物的狀態,就能實現了人物的行走了。
跑動就是連續按兩下左或右,這就需要判斷上一次和這次兩次的按鍵,考慮到後面的絕招等,這裡建立一個儲存按鍵的陣列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;
了便於控制,我將跳躍圖片修改了一下
因為人物動作是透過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]; };
這樣,跳躍就完美實現了。
攻擊的時候,在攻擊動作結束之前,不可能進行走動或跳躍等其他動作的,所以在攻擊鍵按下的時候,需要將按鍵上鎖,讓按鍵無效
setTimeout("keylock = true;",50); hero.setAction(ACTION.ATTACK,hero.direction);
為什麼要使用setTimeout函數? ,因為還有絕招的發動,絕招的發動需要攻擊鍵和跳躍鍵同時按下,但是人不可能同時按下兩個鍵的,要有一個很小的間隔,我這裡將這個間隔的最大值設定為50毫秒,所以在這50毫秒以內,是可以再按下跳躍鍵的。
當連續幾次普通攻擊的時候,是會出現一次特殊的攻擊的,我設定每三次攻擊,進行一次特殊攻擊
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秒鐘內進行三次攻擊,則判定為連續攻擊。
這個也簡單,只要在人物處於跳躍狀態的時候進行攻擊,則判定為跳躍攻擊。
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); }
玩過街機三國志的朋友們都知道,下=>上=>攻擊,就會發動一下特殊的武將技,這個也簡單,在攻擊鍵按下的時候判斷一下前兩次按鍵就可以了。
if(keyLast01.keyCode == KEY.UP && keyLast02.keyCode == KEY.DOWN && keyThis.time - keyLast02.time < 300){ keylock = true; hero.setAction(ACTION.SKILL,hero.direction); }
當滿螢幕的敵人圍住自己的時候,怎麼辦?放大招唄。
在攻击键按下的时候,判断一下跳跃键是不是同时被按下了。
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进行下载。
以上就是[HTML5游戏开发]挑战横版ACT(二):秀身手勇猛如当年的内容,更多相关内容请关注PHP中文网(www.php.cn)!