新聞中心
首先,本篇文章是零基礎(chǔ)開發(fā)RPG游戲-開源講座系列文章的第四篇,來(lái)實(shí)現(xiàn)游戲的腳本化,和利用游戲腳本實(shí)現(xiàn)地圖場(chǎng)景的切換,離上次更新貌似很長(zhǎng)時(shí)間了,你在看下面的文字之前,需要先了解前三篇在下啰嗦了些什么東東。

薩爾圖ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!
一,什么是游戲腳本
簡(jiǎn)單說(shuō),游戲腳本就是依據(jù)一定的格式編寫的可執(zhí)行文件,游戲可以通過(guò)腳本中自定義的語(yǔ)句來(lái)執(zhí)行相應(yīng)的邏輯。
二,為什么要將游戲腳本化
游戲腳本,可以令我們的游戲動(dòng)態(tài)化,比如當(dāng)我們開發(fā)了一款rpg游戲,里面的劇情,事件以及地圖等,我們?nèi)绻麑⑦@些全部寫進(jìn)程序里,當(dāng)然是可以的,但是一旦出現(xiàn)問(wèn)題,哪怕幾個(gè)錯(cuò)別字,我們需要先將這幾個(gè)錯(cuò)別字改正,并且將整個(gè)程序重新編譯發(fā)布一遍,這個(gè)過(guò)程是相當(dāng)令人反感的,因?yàn)槿绻螒虻某绦蚋螒虻膬?nèi)容不斷進(jìn)行修改的話,那只會(huì)使你的程序越來(lái)越復(fù)雜。但是如果我們將這些可重復(fù)的數(shù)據(jù),都定義到游戲程序之外的文件里面,當(dāng)游戲引擎開發(fā)完畢,我們的游戲通過(guò)讀取這些外部文件,來(lái)執(zhí)行相應(yīng)的劇情和事件,那么,像上述當(dāng)我們的游戲出現(xiàn)了問(wèn)題,我們只需要改動(dòng)這些外部文件就可以了,并不需要重新編譯整個(gè)程序,這樣便使得我們的游戲開發(fā),變得便利簡(jiǎn)潔。
當(dāng)然,對(duì)于html5來(lái)說(shuō),不需要重新編譯程序,但是對(duì)于rpg的游戲來(lái)說(shuō),腳本還是必不可少的,因?yàn)橛螒虻膭”静豢赡苋紝懙匠绦蚶?..
三,如何來(lái)實(shí)現(xiàn)游戲的腳本化
好了,接下來(lái),先來(lái)考慮以什么形式來(lái)制作游戲的腳本,我們有多種選擇,可以選擇xml,可以選擇json,也可以選擇純自定義語(yǔ)法,
這次,我為了省事,選用比較方便處理的json,因?yàn)閖avascript可以很輕松的處理json數(shù)據(jù)。
目前游戲中實(shí)現(xiàn)的內(nèi)容有,地圖場(chǎng)景添加,游戲人物添加,以及人物對(duì)話的實(shí)現(xiàn)。那么,我在設(shè)計(jì)游戲腳本的時(shí)候,必須包含這些數(shù)據(jù),然后才能將這三項(xiàng)功能用腳本來(lái)控制。
首先看下面的json
- var script = {
- stage01:{
- map:[
- [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],
- [18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],
- [18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],
- [18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],
- [18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],
- [18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],
- [18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],
- [18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],
- [18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],
- [18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],
- [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]],
- mapdata:[
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
- [1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],
- [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],
- [1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],
- [1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],
- [1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],
- [1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],
- add:[
- {chara:"player",img:"mingren",x:5,y:6},
- {chara:"npc",img:"npc1",x:7,y:6},
- {chara:"npc",img:"npc1",x:3,y:3}],
- talk:{
- talk1:[
- {img:"m",name:"鳴人",msg:"我是木葉村的鳴人,你是誰(shuí)?"},
- {img:"n",name:"黑衣忍者甲",msg:"你就是鳴人?九尾還在你身體里嗎?"}
- ],
- talk2:[
- {img:"n",name:"黑衣忍者乙",msg:"鳴人,聽說(shuō)忍者大戰(zhàn)就要開始了。"},
- {img:"m",name:"鳴人",msg:"真的嗎?一定要想想辦法啊。"}
- ]
- }
- }
- };
我將腳本定義成了變量,實(shí)際游戲制作的時(shí)候,腳本應(yīng)該儲(chǔ)存到一個(gè)外部文檔當(dāng)中,在這里我只是講解一下理論,如何完善那是后話了,哈。
可以看到,json中,包含了地圖相關(guān)的map數(shù)組和mapdata數(shù)組,添加人物的相關(guān)數(shù)據(jù),以及對(duì)話的數(shù)組。這樣,我在游戲顯示的時(shí)候,只需要讀入json數(shù)據(jù),然后根據(jù)這些內(nèi)容來(lái)顯示游戲畫面就可以了,定義一個(gè)initScript函數(shù)來(lái)進(jìn)行這些操作。
- function initScript(){
- //地圖位置初始化
- mapLayer.x = 0;
- mapLayer.y = 0;
- //地圖層初始化
- mapLayer.removeAllChild();
- //人物層初始化
- charaLayer.removeAllChild();
- //效果層初始化
- effectLayer.removeAllChild();
- //對(duì)話層初始化
- talkLayer.removeAllChild();
- //地圖數(shù)據(jù)獲取
- map = stage.map;
- mapdata = stage.mapdata;
- //對(duì)話數(shù)據(jù)獲取
- talkScriptList = stage.talk;
- //添加地圖
- addMap(0,0);
- delMap();
- //添加人物
- addChara();
- }
removeAllChild方法是legendForHtml5Programming引擎獨(dú)有的方法,可以用來(lái)移出LScript顯示層上的所有子對(duì)象,從而實(shí)現(xiàn)本游戲中各個(gè)顯示層的初始化工作。
修改一下addChara方法,如下
- //添加人物
- function addChara(){
- var charaList = stage.add;
- var chara,charaObj;
- for(var i=0;i
- charaObj = charaList[i];
- if(charaObj.chara == "player"){
- //加入英雄
- bitmapdata = new LBitmapData(imglist[charaObj.img]);
- chara = new Character(true,i,bitmapdata,4,4);
- player = chara;
- }else{
- //加入npc
- bitmapdata = new LBitmapData(imglist[charaObj.img]);
- chara = new Character(false,i,bitmapdata,4,4);
- }
- chara.x = charaObj.x * 32;
- chara.y = charaObj.y * 32;
- charaLayer.addChild(chara);
- }
- }
即,根據(jù)json腳本中的add數(shù)組,來(lái)添加游戲中的人物。
好了,運(yùn)行一下游戲,可以看到,游戲正常顯示了,和之前一模一樣,實(shí)現(xiàn)了同樣的功能.
#p#
四,利用游戲腳本實(shí)現(xiàn)地圖的切換
為了讓大家看到游戲腳本的便利性,現(xiàn)在利用腳本實(shí)現(xiàn)游戲中的場(chǎng)景切換。
將json腳本修改如下
- var script = {
- stage01:{
- map:[
- [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],
- [18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],
- [18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],
- [18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],
- [18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],
- [18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],
- [18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],
- [18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],
- [18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],
- [18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],
- [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]],
- mapdata:[
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
- [1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],
- [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],
- [1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],
- [1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],
- [1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],
- [1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],
- add:[
- {chara:"player",img:"mingren",x:5,y:6},
- {chara:"npc",img:"npc1",x:7,y:6},
- {chara:"npc",img:"npc1",x:3,y:3}],
- talk:{
- talk1:[
- {img:"m",name:"鳴人",msg:"我是木葉村的鳴人,你是誰(shuí)?"},
- {img:"n",name:"黑衣忍者甲",msg:"你就是鳴人?九尾還在你身體里嗎?"}
- ],
- talk2:[
- {img:"n",name:"黑衣忍者乙",msg:"鳴人,聽說(shuō)忍者大戰(zhàn)就要開始了。"},
- {img:"m",name:"鳴人",msg:"真的嗎?一定要想想辦法啊。"}
- ]
- },
- jump:[
- {at:{x:6,y:5},to:"stage02"}
- ]
- },
- stage02:{
- map:[
- [0,0,1,2,2,2,2,2,2,2,2,1,0,0,0],
- [0,0,1,3,5,5,1,5,5,5,5,1,0,0,0],
- [0,0,1,80,4,4,1,80,4,4,4,1,0,0,0],
- [0,0,1,80,4,4,1,80,8,7,8,1,0,0,0],
- [0,0,1,80,4,4,5,81,4,4,4,1,0,0,0],
- [0,0,1,2,2,2,6,4,4,4,4,1,0,0,0],
- [0,0,1,3,5,5,81,4,4,4,4,1,0,0,0],
- [0,0,1,80,4,4,4,4,4,4,9,1,0,0,0],
- [0,0,1,2,2,2,2,6,2,2,2,1,0,0,0]],
- mapdata:[
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
- [1,1,1,0,0,0,1,0,0,0,0,1,1,1,1],
- [1,1,1,0,0,0,1,0,0,0,0,1,1,1,1],
- [1,1,1,0,0,0,1,0,0,1,0,1,1,1,1],
- [1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
- [1,1,1,1,1,1,0,0,0,0,0,1,1,1,1],
- [1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
- [1,1,1,0,0,0,0,0,0,0,1,1,1,1,1],
- [1,1,1,1,1,1,1,0,1,1,1,1,1,1,1]],
- add:[
- {chara:"player",img:"mingren",x:7,y:8},
- {chara:"npc",img:"npc1",x:8,y:3},
- {chara:"npc",img:"npc1",x:10,y:3}],
- talk:{
- talk1:[
- {img:"m",name:"鳴人",msg:"你們?cè)诟墒裁窗。?},
- {img:"n",name:"黑衣忍者甲",msg:"我們?cè)诤炔琛?}
- ],
- talk2:[
- {img:"n",name:"黑衣忍者乙",msg:"我們?cè)诤炔瑁悴灰驍_我們。"},
- {img:"m",name:"鳴人",msg:"....."}
- ]
- },
- jump:[
- {at:{x:7,y:8},to:"stage01"}
- ]
- }
- };
可以看到,我添加了stage02,即第二個(gè)場(chǎng)景,并且在腳本里引入了jump節(jié)點(diǎn)來(lái)控制游戲場(chǎng)景的切換,其中jump中的at表示游戲主人公移動(dòng)到達(dá)的坐標(biāo),to表示到達(dá)這個(gè)坐標(biāo)后跳轉(zhuǎn)到的畫面名稱。這里的jump之所以是數(shù)組,是因?yàn)橐粋€(gè)場(chǎng)景也可以跳轉(zhuǎn)到其他多個(gè)場(chǎng)景。
上面的腳本實(shí)現(xiàn)了stage01和stage02兩個(gè)場(chǎng)景的互相跳轉(zhuǎn)。
為了讀取這個(gè)jump,以及實(shí)現(xiàn)跳轉(zhuǎn),我們需要在游戲主人公移動(dòng)一個(gè)步長(zhǎng)之后,判斷一下是否應(yīng)該跳轉(zhuǎn)了,修改Character類的onmove方法
- /**
- * 開始移動(dòng)
- **/
- Character.prototype.onmove = function (){
- var self = this;
- //設(shè)定一個(gè)移動(dòng)步長(zhǎng)中的移動(dòng)次數(shù)
- var ml_cnt = 4;
- //計(jì)算一次移動(dòng)的長(zhǎng)度
- var ml = STEP/ml_cnt;
- //根據(jù)移動(dòng)方向,開始移動(dòng)
- switch (self.direction){
- case UP:
- if(mapmove){
- mapLayer.y += ml;
- charaLayer.y += ml;
- }
- self.y -= ml;
- break;
- case LEFT:
- if(mapmove){
- mapLayer.x += ml;
- charaLayer.x += ml;
- }
- self.x -= ml;
- break;
- case RIGHT:
- if(mapmove){
- mapLayer.x -= ml;
- charaLayer.x -= ml;
- }
- self.x += ml;
- break;
- case DOWN:
- if(mapmove){
- mapLayer.y -= ml;
- charaLayer.y -= ml;
- }
- self.y += ml;
- break;
- }
- self.moveIndex++;
- //當(dāng)移動(dòng)次數(shù)等于設(shè)定的次數(shù),開始判斷是否繼續(xù)移動(dòng)
- if(self.moveIndex >= ml_cnt){
- //一個(gè)地圖步長(zhǎng)移動(dòng)完成后,判斷地圖是否跳轉(zhuǎn)
- if(self.isHero && self.moveIndex > 0)checkJump();
- self.moveIndex = 0;
- //一個(gè)地圖步長(zhǎng)移動(dòng)完成后,如果地圖處于滾動(dòng)狀態(tài),則移除多余地圖塊
- if(mapmove)delMap();
- //如果已經(jīng)松開移動(dòng)鍵,或者前方為障礙物,則停止移動(dòng),否則繼續(xù)移動(dòng)
- if(!isKeyDown || !self.checkRoad()){
- self.move = false;
- return;
- }else if(self.direction != self.direction_next){
- self.direction = self.direction_next;
- self.anime.setAction(self.direction);
- }
- //地圖是否滾動(dòng)
- self.checkMap(self.direction);
- }
- };
我添加了一行
- if(self.isHero && self.moveIndex > 0)checkJump();
表示,移動(dòng)完后如果該人物是游戲主人公則進(jìn)行跳轉(zhuǎn)判斷
所以,我們需要添加一個(gè)checkJump方法
- //游戲場(chǎng)景跳轉(zhuǎn)測(cè)試
- function checkJump(){
- var jump = stage.jump;
- var jumpstage;
- for(var i=0;i
- jumpjumpstage = jump[0];
- if(player.x == jumpstage.at.x * 32 && player.y == jumpstage.at.y * 32){
- //獲取該場(chǎng)景腳本數(shù)據(jù)
- stage = script[jumpstage.to];
- //開始跳轉(zhuǎn)
- initScript(stage);
- return;
- }
- }
- }
好了,一切都很簡(jiǎn)單吧,運(yùn)行游戲看看效果吧,小鳴人走到地圖的小房門的部分是,場(chǎng)景發(fā)生跳轉(zhuǎn)
游戲測(cè)試URL:http://fsanguo.comoj.com/html5/rpg5/index.html
本次更新源代碼下載:http://fsanguo.comoj.com/html5/rpg5/rpg5.rar
網(wǎng)頁(yè)標(biāo)題:HTML 5開發(fā)RPG游戲之四(游戲腳本化)
轉(zhuǎn)載源于:http://m.fisionsoft.com.cn/article/coijpjs.html


咨詢
建站咨詢
