本篇是該系列文章第三篇,其他文章請看下面貼文中的目錄
http ://www.php.cn/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.pideCoordinate(966,88,1,6)); coordinateList.push(LGlobal.pideCoordinate(2268,140,1,7)); var bigskillList = LGlobal.pideCoordinate(2205,830,5,5); coordinateList.push([[bigskillList[0][0],bigskillList[0][1],bigskillList[0][2],bigskillList[0][3],bigskillList[0][4] ,bigskillList[1][0],bigskillList[1][1],bigskillList[1][2],bigskillList[1][3],bigskillList[1][4] ,bigskillList[2][0],bigskillList[2][1],bigskillList[2][2],bigskillList[2][3],bigskillList[2][4] ,bigskillList[3][0],bigskillList[3][1],bigskillList[3][2],bigskillList[3][3],bigskillList[3][4] ,bigskillList[4][0],bigskillList[4][1],bigskillList[4][2],bigskillList[4][3],bigskillList[4][4]]]); var hertList = LGlobal.pideCoordinate(358,87,1,2); coordinateList.push([[hertList[0][0],hertList[0][0],hertList[0][1],hertList[0][1]]]); var fallList = LGlobal.pideCoordinate(2682,157,1,9); coordinateList.push([[fallList[0][0],fallList[0][1],fallList[0][2],fallList[0][3],fallList[0][4],fallList[0][5],fallList[0][6],fallList[0][6],fallList[0][6],fallList[0][7],fallList[0][7],fallList[0][6],fallList[0][6],fallList[0][7],fallList[0][8]]]); //图片位置数据 var locationList = new Array(); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:20,y:20}); locationList.push({x:20,y:20}); locationList.push({x:20,y:20}); locationList.push({x:0,y:0}); locationList.push({x:100,y:0}); locationList.push({x:150,y:20}); locationList.push({x:5,y:0}); locationList.push({x:-30,y:10}); //被攻击范围 var hertList = [[[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50],[-30,-60,60,50]], [[-30,-70,50,60],[-30,-70,50,60],[-30,-70,50,60],[-30,-70,50,60],[-30,-70,50,60],[-30,-70,50,60],[-30,-70,50,60],[-30,-70,50,60]], [[-30,-70,60,60],[-30,-70,60,60],[-30,-70,60,60],[-30,-70,60,60],[-30,-70,60,60],[-30,-70,60,60]], [[-25,-70,50,60],[-25,-70,50,60],[-25,-70,50,60],[-25,-70,50,60],[-25,-70,50,60]], [[-10,-60,30,60],[-10,-60,30,60],[-30,-60,30,60],[-30,-60,30,60]], [[0,-60,40,60],[0,-60,40,60],[-20,-60,30,60],[-20,-60,30,60]], [], [[-20,-60,30,60],[-20,-60,30,60],[-20,-60,30,60],[-20,-60,30,60],[-20,-60,30,60],[-20,-60,30,60]], [[0,-70,40,60],[0,-70,40,60]], [],[],[] ]; //攻击范围 var attackList = [[],[],[],[], [[0,0,0,0],[0,0,0,0],[-10,-70,115,60],[-10,-70,115,60]], [[0,0,0,0],[0,0,0,0],[-10,-100,140,90],[-10,-100,140,90]], [[0,0,0,0],[0,0,0,0],[-10,-130,115,60],[-10,-110,140,120]], [[10,-70,30,70],[10,-70,30,70],[10,-70,30,70],[10,-70,30,70],[10,-70,30,70],[10,-70,30,70]], [[0,0,0,0],[0,0,0,0],[-40,-70,80,60],[-60,-100,80,60],[20,-100,130,100],[20,-100,130,100]], [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0], [50,-105,50,20],[60,-100,120,40],[60,-90,150,40],[50,-80,190,40],[50,-80,210,40], [50,-75,310,60],[50,-75,310,60],[50,-75,310,60],[50,-75,310,80]],[],[] ]; return [dataList,coordinateList,locationList,hertList,attackList]; }, sunji:function(){ //图片数据 var dataList = new Array(); dataList.push(new LBitmapData(imglist["sunji_stand"],0,0,129,89)); dataList.push(new LBitmapData(imglist["sunji_move"],0,0,128,97)); dataList.push(new LBitmapData(imglist["sunji_run"],0,0,125,77)); dataList.push(new LBitmapData(imglist["sunji_jump"],0,0,131,134)); dataList.push(new LBitmapData(imglist["sunji_attack"],0,0,197,103)); dataList.push(new LBitmapData(imglist["sunji_big_attack"],0,0,198,103)); dataList.push(new LBitmapData(imglist["sunji_jump_attack"],0,0,182,143)); dataList.push(new LBitmapData(imglist["sunji_hit"],0,0,238,86)); dataList.push(new LBitmapData(imglist["sunji_skill"],0,0,215,102)); dataList.push(new LBitmapData(imglist["sunji_big_skill"],0,0,275,139)); dataList.push(new LBitmapData(imglist["sunji_hert"],0,0,131,79)); dataList.push(new LBitmapData(imglist["sunji_fall"],0,0,249,136)); //图片分割数据 var coordinateList = new Array(); coordinateList.push(LGlobal.pideCoordinate(1548,89,1,12)); coordinateList.push(LGlobal.pideCoordinate(640,97,1,5)); coordinateList.push(LGlobal.pideCoordinate(1000,77,1,8)); 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(394,103,1,2); coordinateList.push([[attackList[0][0],attackList[0][1],attackList[0][1],attackList[0][1]]]); var bigattackList = LGlobal.pideCoordinate(792,103,1,4); coordinateList.push(bigattackList); var jumpattackList = LGlobal.pideCoordinate(728,143,1,4); coordinateList.push(jumpattackList); coordinateList.push(LGlobal.pideCoordinate(1428,86,1,6)); coordinateList.push(LGlobal.pideCoordinate(2365,102,1,11)); var bigskillList = LGlobal.pideCoordinate(1650,695,5,6); coordinateList.push([[bigskillList[0][0],bigskillList[0][1],bigskillList[0][2],bigskillList[0][3],bigskillList[0][4],bigskillList[0][5] ,bigskillList[1][0],bigskillList[1][1],bigskillList[1][2],bigskillList[1][3],bigskillList[1][4],bigskillList[1][5] ,bigskillList[2][0],bigskillList[2][1],bigskillList[2][2],bigskillList[2][3],bigskillList[2][4],bigskillList[2][5] ,bigskillList[3][0],bigskillList[3][1],bigskillList[3][2],bigskillList[3][3],bigskillList[3][4],bigskillList[3][5] ,bigskillList[4][0],bigskillList[4][1],bigskillList[4][2],bigskillList[4][3],bigskillList[4][4],bigskillList[4][5]]]); var hertList = LGlobal.pideCoordinate(262,79,1,2); coordinateList.push([[hertList[0][0],hertList[0][0],hertList[0][1],hertList[0][1]]]); var fallList = LGlobal.pideCoordinate(1245,544,4,5); coordinateList.push([[fallList[0][0],fallList[0][1],fallList[0][2],fallList[0][3],fallList[0][4],fallList[1][0],fallList[1][1],fallList[1][2],fallList[1][3],fallList[1][4],fallList[2][0],fallList[2][1],fallList[2][2],fallList[2][3],fallList[2][4],fallList[3][0],fallList[3][1],fallList[3][2],fallList[3][3],fallList[3][4]]]); //图片位置数据 var locationList = new Array(); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:40,y:8}); locationList.push({x:20,y:0}); locationList.push({x:20,y:20}); locationList.push({x:0,y:0}); locationList.push({x:0,y:0}); locationList.push({x:70,y:10}); locationList.push({x:5,y:0}); locationList.push({x:-35,y:0}); //被攻击范围 var hertList = [[[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60],[-25,-70,60,60]], [[-25,-90,50,80],[-25,-90,50,80],[-25,-90,50,80],[-25,-90,50,80],[-25,-90,50,80],[-25,-90,50,80],[-25,-90,50,80],[-25,-90,50,80]], [[-30,-60,70,40],[-30,-60,70,40],[-30,-60,70,40],[-30,-60,70,40],[-30,-60,70,40],[-30,-60,70,40]], [[-25,-90,50,70],[-25,-90,50,70],[-25,-90,50,70],[-25,-90,50,70],[-25,-90,50,70]], [[-20,-80,50,70],[-20,-80,50,70],[-10,-60,70,50],[-10,-60,70,50]], [[-10,-80,50,60],[-10,-80,50,60],[-10,-80,50,60],[-10,-80,50,60]], [[-30,-80,50,70],[-30,-80,50,70],[-30,-80,50,70],[-30,-80,50,70]], [[-20,-70,60,60],[-20,-70,60,60],[-20,-70,60,60],[-20,-70,60,60],[-20,-70,60,60],[-20,-70,60,60]], [[-10,-80,40,70],[-10,-80,40,70]], [],[],[] ]; //攻击范围 var attackList = [[],[],[],[], [[0,0,0,0],[0,0,0,0],[30,-70,75,60],[30,-70,75,60]], [[0,0,0,0],[0,0,0,0],[20,-100,80,90],[20,-100,80,90]], [[0,0,0,0],[0,0,0,0],[-10,-90,100,80],[-10,-90,100,80]], [[10,-70,50,70],[10,-70,50,70],[10,-70,50,70],[10,-70,50,70],[10,-70,50,70],[10,-70,50,70]], [[0,0,0,0],[0,0,0,0],[-30,-70,90,60],[-90,-70,130,60],[-100,-80,140,70],[-40,-80,140,70]], [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,-100,100,40],[0,-110,100,50],[0,-110,100,50], [0,0,0,0],[20,-120,140,120],[20,-120,130,120],[-50,-120,160,120],[-60,-80,180,80], [-20,-50,150,60],[-10,-60,150,60],[50,-60,90,60],[50,-75,150,70],[50,-75,150,70], [50,-75,150,70],[50,-75,150,70]],[],[] ]; return [dataList,coordinateList,locationList,hertList,attackList]; } }
這樣一來,就直接透過這些事先設定好的範圍來偵測是否碰撞就可以了,這樣的矩形碰撞該如何偵測呢?當然就用到了lufylegend.js引擎中的一個矩形類LRectangle,具體用法請參考官方的Api文檔,本次用到的碰撞檢測是intersects()函數,這個函數用來檢測兩個LRectangle對像是否重疊,即是否碰撞。
因為我方和地方都是可以攻擊的,所以攻擊的偵測載入父類別Character裡,在Character類別的onframe函數裡加入下面程式碼。
if(self.action == ACTION.ATTACK || self.action == ACTION.BIG_ATTACK || self.action == ACTION.HIT || self.action == ACTION.JUMP_ATTACK || self.action == ACTION.SKILL || self.action == ACTION.BIG_SKILL){ for(key in charaLayer.childList){ chara = charaLayer.childList[key]; if(self.belong == chara.belong)continue; self.checkAction(chara); } }
是說,當前人物的動作處於攻擊等動作的時候,並且是敵人的時候,進入攻擊檢測checkAction函數,checkAction函數如下。
Character.prototype.checkAction = function (chara){ var self = this; var attack_rect = self.getAttackRect(); var hert_rect = chara.getHertRect(); if(!attack_rect || !hert_rect)return; if(attack_rect.intersects(hert_rect) && Math.abs(self.y - chara.y) < 30){ if(self.action == ACTION.ATTACK){ chara.setAction(ACTION.HERT,chara.direction); }else{ var dir = DIRECTION.RIGHT; if(self.x < chara.x)dir = DIRECTION.LEFT; chara.setAction(ACTION.FALL,dir); } } }
getAttackRect函数和getHertRect函数分别返回当前的攻击和被攻击的范围LRectangle对象,然后通过intersects函数判断是否攻击到了对方,如果是普通攻击,则被攻击方变为被攻击状态,其他攻击方式的话,变为摔倒状态。
getAttackRect和getHertRect函数如下。
Character.prototype.getAttackRect = function(){ var self = this; attackList = self.attackList[self.action]; if(self.anime.colIndex >= attackList.length)return false; var rect = attackList[self.anime.colIndex]; var x = rect[0],y=rect[1],w=rect[2],h=rect[3]; if(x == 0 && y == 0 && w == 0 && h == 0)return false; y += self.y; if(self.direction == DIRECTION.LEFT){ x = self.x - x - w; }else{ x = self.x +x; } return new LRectangle(x,y,w,h); } Character.prototype.getHertRect = function(){ var self = this; var hertList = self.hertList[self.action]; if(self.anime.colIndex >= hertList.length)return false; var rect = hertList[self.anime.colIndex]; var x = rect[0],y=rect[1],w=rect[2],h=rect[3]; if(x == 0 && y == 0 && w == 0 && h == 0)return false; y += self.y; if(self.direction == DIRECTION.LEFT){ x = self.x - x - w; }else{ x = self.x +x; } return new LRectangle(x,y,w,h); }
好了,剩下的敌人的AI和声效等部分,咱们留着以后再继续。现在,大家可以点击下面的测试连接,看看本次的成果了
http://lufy.netne.net/lufylegend-js/act03/index.html
黄老将军听说即将登场的是孙尚香后激动不已,那叫一个美啊,眼睛整个眯成了一个心形,大吼着,尚香啊,老夫等你几百年了。这是在令我大吃一惊,孙尚香不是刘备老婆吗,是这老家伙的主子啊,这真是太不像话了。可老将军在一旁兴奋的吼着,“靠!我会让你知道我暗恋她几百年吗?老夫绝对不会承认的。”,“如果当年我年轻个几十年,呸,我怎么会这么想,她毕竟是主公的老婆。”,“不对,主公也老了。啊,老夫可是忠臣,我是不会跟主公抢的。”,“老夫什么都没说。lufy,你给我听着,老夫什么都没说。”。我急忙说“啊啊,我什么都没听见啊……”
不过,这有什么用啊,这老家伙一上场,就开始往前跑,边跑边嘟囔“妞,给大爷摸一个……”。由于某种原因,这里省略1000字。
终于,孙尚香出现了,老黄忠一下子就扑了过去,刚伸手去摸了一把,就发现孙尚香被他打的满地跑,立马吼道“lufy,老夫要的是摸,不是砍啊”。
lufy:“哼哼,老色鬼,我岂能给你方便,让你得逞……”,另外他还不知道在前面,还给他准备了另一个黄忠,一个孙尚香,看他们怎么抢吧,哈哈。
唉,真是:
神箭威名数黄忠,斩将杀敌显神通。百年宝刀仍未老,一遇红颜梦成空。
现在给出本次源码下载,喜欢的可以看一下。
http://fsanguo.comoj.com/download.php?i=act03.rar
注意:该附件只包含本次文章源码,lufylegend.js引擎请到http://lufylegend.com/lufylegend进行下载。
以上就是[HTML5游戏开发]挑战横版ACT(三):遇红颜英雄亦多情的内容,更多相关内容请关注PHP中文网(www.php.cn)!