《遊戲指令碼的設計與開發》-(戰棋部分)第八章 軍隊降臨戰場

來源:互聯網
上載者:User

上次講了如何快速顯示一張戰場地圖,有了戰場沒有軍隊怎麼行,本次來向戰場上添加軍隊。一般戰棋遊戲中,戰場上的軍隊有三種,我軍,敵軍和友軍。我軍是可操縱的,敵軍是可攻擊的,友軍是不可操縱,也不可攻擊的。敵軍和友軍之間會相互攻擊。當然,一些更複雜的遊戲中,以不同的勢力來區分,之間的攻擊關係以它們之間的敵對或同盟等關係來決定。

製作開始,軍隊降臨

本指令碼中的戰棋遊戲是以曹操傳為參考對象的,軍隊分我軍,敵軍和友軍,在L#指令碼中,添加軍隊的指令碼如下。

//我軍添加(我軍人員出戰序號,面向,座標x,座標y,顯示或隱藏)SouSouSCharacter.addOur(0,0,6,6,1);//敵軍添加(人物序號,出場等級,面向,座標x,座標y,顯示或隱藏,行動AI)SouSouSCharacter.addEnemy(1,1,0,8,4,1,0);//友軍添加(人物序號,出場等級,面向,座標x,座標y,顯示或隱藏,行動AI)SouSouSCharacter.addFriend(2,1,0,6,4,1,0);

上面的指令碼分別是,我軍添加,敵軍添加和友軍添加和相關的參數設定。

軍隊添加的指令碼也是下面的指令碼之間,且需要再addMap指令碼之前。

initialization.start;initialization.end;

也就是說,軍隊添加的指令碼正確格式如下。

initialization.start;SouSouSCharacter.addOur(0,0,6,6,1);SouSouSCharacter.addEnemy(1,1,0,8,4,1,0);SouSouSCharacter.addFriend(2,1,0,6,4,1,0);addMap(s01.smap);initialization.end;

這幾個指令碼的解析過程如下:

switch(lineValue.substr(0,start)){case "addMap":LSouSouObject.sMap.addMap(lineValue.substring(start+1,end).split(","));break;case "SouSouSCharacter.addOur":LSouSouObject.sMap.addOurCharacter(lineValue.substring(start+1,end).split(","));break;case "SouSouSCharacter.addEnemy":LSouSouObject.sMap.addEnemyCharacter(lineValue.substring(start+1,end).split(","));break;case "SouSouSCharacter.addFriend":LSouSouObject.sMap.addFriendCharacter(lineValue.substring(start+1,end).split(","));break;default:LSouSouSMapScript.initialization();}

為了實現軍隊的添加,需要預先準備好人物的設定,建立一個chara.json如下

{"peo1":{"Index":"1","Name":"劉備","Face":"0","R":"0","S":"0","Arms":"1","Lv":"1","Exp":"1","Troops":"104","Strategy":"30","MaxTroops":"104","MaxStrategy":"30","Force":"78","Intelligence":"76","Command":"72","Agile":"74","Luck":"100","Skill":"1","Introduction":"劉備即蜀漢昭烈帝,字玄德,漢中山靖王劉勝的後代,三國時期蜀漢開國皇帝。"},"peo2":{"Index":"2","Name":"關羽","Face":"1","R":"1","S":"1","Arms":"4","Lv":"1","Exp":"1","Troops":"107","Strategy":"13","MaxTroops":"107","MaxStrategy":"13","Force":"96","Intelligence":"90","Command":"98","Agile":"68","Luck":"62","Skill":"2","Introduction":"關羽本字長生,後改字雲長。東漢末年著名將領,自劉備於鄉裡聚眾起兵開始追隨劉備,是劉備的結義兄弟,也是劉備最為信任的將領之一。"},"peo3":{"Index":"3","Name":"張飛","Face":"2","R":"2","S":"2","Arms":"4","Lv":"1","Exp":"1","Troops":"105","Strategy":"9","MaxTroops":"105","MaxStrategy":"9","Force":"99","Intelligence":"46","Command":"74","Agile":"72","Luck":"76","Skill":"3","Introduction":"張飛,字翼德,三國時期蜀漢重要將領,自劉備於鄉裡聚眾起兵開始追隨劉備,是劉備的結義兄弟,也是劉備最為信任的將領之一。"}}

chara.json檔案是所有人物資料的設定,本次先暫時添加三個人物,為了方便這些人物資料的管理,先加入一個LSouSouMember類,代碼如下

function LSouSouMember(data,flag){var self = this;if(data){self.data = data;}}LSouSouMember.prototype.getIndex = function(){return this.data.Index;};LSouSouMember.prototype.getS = function(){return this.data.S;};

當然,上面並不是完整的LSouSouMember類,以後會繼續慢慢擴充。曹操傳的S戰場劇本中,我軍加入和敵友軍加入有些不同,敵友軍出場設定中,第一個參數需要的是人物在chara.json中的序號,而我軍出場是由選定出戰的我軍的人員來決定的,所以第一個參數是我軍人員的出場順序號。我軍出場的人員選定,也是由指令碼來控制的,不過遊戲開發還沒到那一步,所以先預先轉備好出場人員,以後再進行指令碼化。在LSouSouSMap類的構造器中加入我軍出場人員,並且添加一個_charaLayer層,來顯示戰場上的軍隊,以下是完整的LSouSouSMap構造器。

function LSouSouSMap(){var self = this;base(self,LSprite,[]);LSouSouObject.sMap = self;self.nodeLength = 48;self._objectData = null;self._loadBar = null;self._mapData = null;self.mapW = 0;self.mapH = 0;self.ourlist = [];self.enemylist = [];self.friendlist = [];self._mapLayer = new LSprite();self._charaLayer = new LSprite();self._viewMapLayer = new LSprite();//暫時添加,後面會指令碼化LSouSouObject.memberList.push(new LSouSouMember(LGlobal.chara["peo1"]));LSouSouObject.perWarList.push(LGlobal.chara["peo1"].Index);self.addChild(self._mapLayer);self.addChild(self._charaLayer);self.addChild(self._viewMapLayer);LGlobal.script.scriptLayer.addChild(self);LSouSouSMapScript.analysis();}

為了實現軍隊的添加,給LSouSouSMap類加上下面三個函數,分別用來添加我軍,敵軍和友軍。

LSouSouSMap.prototype.addOurCharacter = function(param){var self = this;//判斷出戰人員是否合法,LSouSouObject.perWarList是我軍所選出戰人員if(parseInt(param[0]) >= LSouSouObject.perWarList.length){LSouSouSMapScript.initialization();return;}var i,mbr,_characterS;//確定出戰人員資料,LSouSouObject.memberList是加入我方的所有人員for(i=0;i<LSouSouObject.memberList.length;i++){mbr = LSouSouObject.memberList[i];if(mbr.getIndex() == LSouSouObject.perWarList[parseInt(param[0])])break;}//將出戰人員加入到戰場中的_charaLayer層_characterS = new LSouSouCharacterS(mbr,0,parseInt(param[1]),0);self._charaLayer.addChild(_characterS);//出戰人員位置確定_characterS.x = parseInt(param[2])*LSouSouObject.sMap.nodeLength;_characterS.y = parseInt(param[3])*LSouSouObject.sMap.nodeLength;//出戰人員移動目標,人物移動是會用到_characterS.tagerCoordinate = new LPoint(_characterS.x,_characterS.y);//出戰人員是否隱藏設定if(parseInt(param[4]) == 0)_characterS.visible = false;//將出戰人員添加到我軍人員ourlist數組LSouSouObject.sMap.ourlist.push(_characterS);LSouSouSMapScript.initialization();};LSouSouSMap.prototype.addEnemyCharacter = function(param){var self = this;var i,mbr,_characterS;//確定出戰人員資料var memberData = LGlobal.chara["peo"+param[0]];mbr = new LSouSouMember(memberData);//將出戰人員加入到戰場中的_charaLayer層_characterS = new LSouSouCharacterS(mbr,1,parseInt(param[2]),parseInt(param[6]));self._charaLayer.addChild(_characterS);//出戰人員位置確定_characterS.x = parseInt(param[3])*LSouSouObject.sMap.nodeLength;_characterS.y = parseInt(param[4])*LSouSouObject.sMap.nodeLength;//出戰人員移動目標,人物移動是會用到_characterS.tagerCoordinate = new LPoint(_characterS.x,_characterS.y);//出戰人員是否隱藏設定if(parseInt(param[5]) == 0)_characterS.visible = false;//將出戰人員添加到敵軍人員enemylist數組LSouSouObject.sMap.enemylist.push(_characterS);LSouSouSMapScript.initialization();};LSouSouSMap.prototype.addFriendCharacter = function(param){var self = this;var i,mbr,_characterS;//確定出戰人員資料var memberData = LGlobal.chara["peo"+param[0]];mbr = new LSouSouMember(memberData);//將出戰人員加入到戰場中的_charaLayer層_characterS = new LSouSouCharacterS(mbr,1,parseInt(param[2]),parseInt(param[6]));self._charaLayer.addChild(_characterS);//出戰人員位置確定_characterS.x = parseInt(param[3])*LSouSouObject.sMap.nodeLength;_characterS.y = parseInt(param[4])*LSouSouObject.sMap.nodeLength;//出戰人員移動目標,人物移動是會用到_characterS.tagerCoordinate = new LPoint(_characterS.x,_characterS.y);//出戰人員是否隱藏設定if(parseInt(param[5]) == 0)_characterS.visible = false;//將出戰人員添加到友軍人員friendlist數組LSouSouObject.sMap.friendlist.push(_characterS);LSouSouSMapScript.initialization();};

LSouSouCharacterS類,是戰場上的人物類,包含戰場上人物的所有行動控制,以及AI屬性等,在lufylegend.js引擎中,顯示人物動畫,一般是用LAnimation類來實現的,但是用LAnimation類來顯示動畫的時候,使用的圖片必須是一張圖片,也就是說,人物的所需要播放的動作需要繪製到一張圖片上,然後進行切割播放。但是,曹操傳中,戰場上的人物圖片一共分為下面三個

因為要顯示的動畫,分別分配在三張圖片中,所以用LAnimation類來實現的話,就有點麻煩了,所以,這裡顯示動畫,就直接用LBitmap來實現了,只要控制好LBitmap中的LBitmapData對象,同樣可以完成動畫的顯示。看下面的代碼

function LSouSouCharacterS(member,belong,direct,command){var self = this;base(self,LSouSouCharacter,[]);self._member = member;self._belong = belong;self._direction = direct;self._command = command;self.animeList = [];self.action = 0;self.actionIndex = 0;self.image = {};self.image["atk"] = new LBitmapData(LGlobal.imglist["s-view-atk"]);self.image["mov"] = new LBitmapData(LGlobal.imglist["s-view-mov"]);self.image["spc"] = new LBitmapData(LGlobal.imglist["s-view-spc"]);self.image["mov"].setProperties(0,0,48,48);self.bitmap = new LBitmap(self.image["mov"]);self.addChild(self.bitmap);self.setImage();}LSouSouCharacterS.prototype.setImage = function(){var self = this;var atklist = LGlobal.divideCoordinate(self.image["atk"].image.width,self.image["atk"].image.height,12,1);var movlist = LGlobal.divideCoordinate(self.image["mov"].image.width,self.image["mov"].image.height,11,1);var spclist = LGlobal.divideCoordinate(self.image["spc"].image.width,self.image["spc"].image.height,5,1);var list;/*********站立*********///下list = [ "mov", 48, 48, [[movlist[6][0],1]] ];self.animeList.push(list);//左list = [ "mov", 48, 48, [[movlist[8][0],1]] ];self.animeList.push(list);//上list = [ "mov", 48, 48, [[movlist[7][0],1]] ];self.animeList.push(list);//右list = [ "mov", 48, 48, [[movlist[8][0],-1]] ];self.animeList.push(list);/*********移動*********///下list = [ "mov", 48, 48, [ [movlist[0][0], 1], [movlist[1][0], 1] ] ];self.animeList.push(list);//左list = [ "mov", 48, 48, [ [movlist[4][0], 1], [movlist[5][0], 1] ] ];self.animeList.push(list);//上list = [ "mov", 48, 48, [ [movlist[2][0], 1], [movlist[3][0], 1] ] ];self.animeList.push(list);//右list = [ "mov", 48, 48, [ [movlist[4][0], -1], [movlist[5][0], -1] ] ];self.animeList.push(list);self.action = self._direction+4;};

在一個戰棋遊戲中,戰場上的軍隊可以說是多種多樣,每個兵種所用的圖片都是不同的,而特殊的人物也有其特殊的形象,所用的圖片也是不同的。這樣一來,所需要的圖片就是比較多的,一個遊戲中所用的戰場形象可能有幾十個甚至上百個,要想快速進入戰場的話,就需要預先讀取所有形象。在本地遊戲中,讀取這些圖片也是不需要多少時間的,可是在頁遊上就需要注意了。所以我在添加戰場人物LSouSouCharacterS時,預先將人物形象設定為準備好的形象圖片,運行後的效果如下。

LSouSouCharacterS類的setImage函數,是將三張人物形象的動作進行分解,將【站立】,【移動】,【攻擊】,【防禦】......等每一個動作都壓入到animeList數組中。本次暫時分解【站立】,【移動】兩個動作。前面說了,本次顯示人物動畫,是直接使用LBitmap對象,通過控制LBitmap對象中的LBitmapData對象來實現動畫的播放。在setImage函數中被壓入animeList數組中的元素依次為[LBitmapData對象名稱,形象的寬,形象的高,動畫座標組 ],其中的動畫座標組是由圖片地區座標以及圖片是否翻轉組成的一組序列,具體為[ [地區座標,圖片是否翻轉], [地區座標,圖片是否翻轉] ],這裡的地區座標不太好解釋,舉個例子,比如下面這個圖片。

圖中紅色矩形框為顯示地區,由於每個小動作圖片的大小為48x48,則地區座標為(0,48)。這樣一來,如果要播放動畫,則將animeList中的相應的動作,對應的地區座標數組中的元素,依次替換當前的人物的LBitmapData對象,就會實現動畫,具體實現的話,先要添加LEvent.ENTER_FRAME事件如下。

self.speed = 2;self.speedIndex = 0;self.addEventListener(LEvent.ENTER_FRAME,self.onframe);

onframe函數代碼如下

LSouSouCharacterS.prototype.onframe = function(self){if(self.speedIndex++ < self.speed)return;self.speedIndex = 0;var anime = self.animeList[self.action]var list = anime[3];if(self.actionIndex >= list.length){self.actionIndex = 0;}var obj = list[self.actionIndex++];var coordinate = obj[0];self.bitmap.bitmapData = self.image[anime[0]];self.bitmap.bitmapData.setProperties(coordinate.x,coordinate.y,anime[1],anime[2]);self.bitmap.scaleX = obj[1];};

以上代碼,雖然實現了動畫的播放,但是所用的圖片依然是預先設定的黑色動作圖片,所有人物都是一樣的,如果要實現戰場人物的多樣化,只需要根據chara.json資料中的設定,讀取相應的戰場形象圖片,待讀取完圖片之後,替換掉LSouSouCharacterS類中原來所用的圖片就可以了,具體實現如下。

LSouSouCharacterS.prototype.loadImage = function(){var self = this;atkLoader = new LLoader();atkLoader.parent = self;atkLoader.addEventListener(LEvent.COMPLETE,self.loadAtkOver);atkLoader.load("images/characters/s/" + self._member.getS() +"/atk.png" + (LGlobal.traceDebug?("?"+(new Date()).getTime()):""),"bitmapData");movLoader = new LLoader();movLoader.parent = self;movLoader.addEventListener(LEvent.COMPLETE,self.loadMovOver);movLoader.load("images/characters/s/" + self._member.getS() +"/mov.png" + (LGlobal.traceDebug?("?"+(new Date()).getTime()):""),"bitmapData");spcLoader = new LLoader();spcLoader.parent = self;spcLoader.addEventListener(LEvent.COMPLETE,self.loadSpcOver);spcLoader.load("images/characters/s/" + self._member.getS() +"/spc.png" + (LGlobal.traceDebug?("?"+(new Date()).getTime()):""),"bitmapData");};LSouSouCharacterS.prototype.loadAtkOver = function(event){var self = event.target.parent;self.image["atk"] = new LBitmapData(event.currentTarget);};LSouSouCharacterS.prototype.loadMovOver = function(event){var self = event.target.parent;self.image["mov"] = new LBitmapData(event.currentTarget);};LSouSouCharacterS.prototype.loadSpcOver = function(event){var self = event.target.parent;self.image["spc"] = new LBitmapData(event.currentTarget);};

人物形象讀取完之後,將圖片替換後的效果如下

測試連接如下

http://lufylegend.com/demo/test/lsharp/09/game/index.html

以上,本章就先講這麼多了,下一章講一講戰場上的尋路演算法,讓軍隊在戰場上進行移動。

本章為止的源碼如下,不包含lufylegend.js引擎源碼,請自己到官網下載

http://lufylegend.com/demo/test/lsharp/09/09.rar

※源碼運行說明:需要伺服器支援,詳細請看本系列文章《序》和《第一章》

《遊戲指令碼的設計與開發》系列文章目錄

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

本章就講到這裡,歡迎繼續關注我的部落格

轉載請註明:轉自lufy_legend的部落格http://blog.csdn.net/lufy_legend

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.