lufy前輩寫過《[代碼藝術]17行代碼的貪吃蛇小遊戲》一文,忽悠了不少求知的兄弟進去閱讀,閱讀量當然是相當的大。今天我不仿也搞一個這樣的教程,目地不在於忽悠人,而在於協助他人。
先看demo:
測試URL:
http://www.cnblogs.com/yorhom/articles/3157553.html
關注我的blog的人不仿會看到我最近發布了新引擎lufylegendRPG 1.0.0,今天就算來推廣一下這個引擎吧。也好讓大家見證一下封裝的力量。
引擎:http://www.cnblogs.com/yorhom/archive/2013/06/08/3126534.html
lufylegendRPG 1.0.0發布帖:http://blog.csdn.net/yorhomwang/article/details/9103451
首先為了不讓大家質疑,我先聲明,我這裡說的145代碼沒有經過壓縮和格式最佳化,只不過這裡是沒有包含指令碼的……畢竟指令碼太大了嘛……
(lufy前輩一定心中在想:“你還不是忽悠人,還冤枉我”)
話不多講,把145行代碼上給大家看看:
LSystem.screen(LStage.FULL_SCREEN);init(50,"mylegend",480,288,main);LGlobal.setDebug(true);LRPG.setShortcuts(true);var backLayer,loadingLayer;var loadData = [{path:"./js/script.js",type:"js"},{name:"map",path:"./images/map01.jpg"},{name:"player",path:"./images/p0.png"},{name:"npc",path:"./images/p1.png"},{name:"m",path:"./images/m.jpg"},{name:"n",path:"./images/n.jpg"},{name:"talk",path:"./images/back.png"},{name:"e1",path:"./images/e1.png"},{name:"e2",path:"./images/e2.png"}];var datalist = [];var map,mapData;var charaList;var talkContent;var jumpTo;var stage;var isJumpMap = false;var stageObj;var dir = "";function main(){loadingLayer = new LoadingSample3(); addChild(loadingLayer); LLoadManage.load(loadData,function(progress){loadingLayer.setProgress(progress);},gameInit);}function gameInit(result){removeChild(loadingLayer);datalist = result;initLayer();initScriptData();stage = script.stage01;initScript();addCtrl();}function initLayer(){backLayer = new LSprite();addChild(backLayer);ctrlLayer = new LSprite();addChild(ctrlLayer);}function addScene(){var mapObj = new LTileMap(map,datalist["map"],32,32,mapData);var stageData = new LSceneData(mapObj,charaList,talkContent);stageObj = new LScene(stageData);backLayer.addChild(stageObj);var talkBoardData = new LBitmapData(datalist["talk"]);var talkBoard = new LBitmap(talkBoardData);talkBoard.scaleX = 28;talkBoard.scaleY = 6.2;talkBoard.x = 100;talkBoard.y = 70;talkBoard.alpha = 0.7;stageObj.talk.x = 120;stageObj.talk.y = 30;stageObj.setTalkStyle({x:-80,y:20},{x:20,y:55,size:12,color:"lightgray"},{x:20,y:85,size:10,color:"lightgray"},talkBoard,200);stageObj.addMoveEventListener(LEvent.COMPLETE,function(){for(var i=0;i<jumpTo.length;i++){if(isJumpMap == false && stageObj.playerX == jumpTo[i].at.x && stageObj.playerY == jumpTo[i].at.y){stage = script[jumpTo[i].to];initScript();isJumpMap = true;}if(isJumpMap == true)isJumpMap = false;}});}function addCtrl(){var bitmapdata = new LBitmapData(datalist["e1"]);var bitmap = new LBitmap(bitmapdata);bitmap.x = 0;bitmap.y = 0;ctrlLayer.addChild(bitmap);var bitmapdata = new LBitmapData(datalist["e2"]);var bitmap = new LBitmap(bitmapdata);bitmap.x = 280;bitmap.y = 30;ctrlLayer.addChild(bitmap);ctrlLayer.x = 40;ctrlLayer.y = 160;addEvent();}function addEvent(){backLayer.addEventListener(LMouseEvent.MOUSE_DOWN,ondown);backLayer.addEventListener(LMouseEvent.MOUSE_UP,onup);backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);}function ondown(event){if(event.offsetX >= ctrlLayer.x + 40 && event.offsetX <= ctrlLayer.x+80){if(event.offsetY >= ctrlLayer.y && event.offsetY <= ctrlLayer.y+40){dir = "UP";}else if(event.offsetY >= ctrlLayer.y+80 && event.offsetY <= ctrlLayer.y+120){dir = "DOWN";}}else if(event.offsetX >= ctrlLayer.x && event.offsetX <= ctrlLayer.x+40){dir = "LEFT";}else if(event.offsetX >= ctrlLayer.x+80 && event.offsetX <= ctrlLayer.x+120){dir = "RIGHT";}}function onup(event){dir = "";if(event.offsetX >= ctrlLayer.x + 280 && event.offsetX <= ctrlLayer.x+330){if(event.offsetY >= ctrlLayer.y+40 && event.offsetY <= ctrlLayer.y+100){stageObj.startTalk();}}}function onframe(){switch(dir){case "UP":stageObj.movePlayer(LPlayerMove.UP);break;case "DOWN":stageObj.movePlayer(LPlayerMove.DOWN);break;case "LEFT":stageObj.movePlayer(LPlayerMove.LEFT);break;case "RIGHT":stageObj.movePlayer(LPlayerMove.RIGHT);break;}}
可以看到,代碼是還是老樣子,沒有一點壓縮。其實這裡面大家沒有看到一點資料是因為我把資料放在了指令碼裡,指令碼可以是一種特定格式的語言,可以用自訂的,比如像lufy前輩的L#。當然在js裡也可以用xml和json,json比較方便,所以這次就選擇了它,裡面的代碼如下:
var script;function initScriptData(){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,17],[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,0],[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",data:datalist["player"],row:4,col:4,speed:3,x:5,y:6},{chara:"npc",talkIndex:1,data:datalist["npc"],row:4,col:4,speed:3,x:7,y:7},{chara:"npc",talkIndex:2,data:datalist["npc"],row:4,col:4,speed:3,x:3,y:3}],talk:{1:[{face:datalist["m"],name:"[鳴人]",msg:"我是木葉村的鳴人,你是誰?"},{face:datalist["n"],name:"[黑衣忍者甲]",msg:"你就是鳴人?九尾還在你身體裡嗎?"}],2:[{face:datalist["n"],name:"[黑衣忍者乙]",msg:"鳴人,聽說忍者大戰就要開始了。"},{face:datalist["m"],name:"[鳴人]",msg:"真的嗎?一定要想想辦法啊。"}]},jump:[{at:{x:6,y:5},to:"stage02"},{at:{x:16,y:6},to:"stage03"}]},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",data:datalist["player"],row:4,col:4,speed:3,x:7,y:8},{chara:"npc",talkIndex:1,data:datalist["npc"],row:4,col:4,speed:3,x:8,y:3},{chara:"npc",talkIndex:2,data:datalist["npc"],row:4,col:4,speed:3,x:10,y:3}],talk:{1:[{face:datalist["m"],name:"[鳴人]",msg:"你們在幹什麼啊?"},{face:datalist["n"],name:"[黑衣忍者甲]",msg:"我們在喝茶。"}],2:[{face:datalist["n"],name:"[黑衣忍者乙]",msg:"我們在喝茶,你不要打擾我們。"},{face:datalist["m"],name:"[鳴人]",msg:"....."}]},jump:[{at:{x:7,y:8},to:"stage01"}]},stage03:{map:[[55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55],[55,55,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19],[55,55,19,19,19,18,19,19,18,18,18,18,17,17,17,17,19],[55,55,55,19,19,19,19,19,19,18,18,17,17,17,19,19,19],[55,19,55,19,19,18,19,19,18,19,17,17,17,17,19,18,19],[55,19,19,19,19,19,18,19,18,19,17,17,17,17,19,19,19],[10,11,11,11,11,11,11,12,17,17,17,17,17,17,19,18,19],[55,19,19,19,19,19,19,16,11,56,57,17,17,17,19,19,19],[55,18,17,17,77,16,16,16,16,55,55,17,17,17,19,19,19],[55,19,17,17,77,16,16,16,16,55,55,18,18,19,19,19,18],[55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55]],mapdata:[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1],[1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1],[1,1,1,1,1,1,1,0,0,1,1,0,0,0,1,1,1],[1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1],[1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],add:[{chara:"player",data:datalist["player"],row:4,col:4,speed:3,x:1,y:6},{chara:"npc",talkIndex:1,data:datalist["npc"],row:4,col:4,speed:3,x:8,y:7}],talk:{1:[{face:datalist["m"],name:"[鳴人]",msg:"這是哪裡?好美啊。"},{face:datalist["n"],name:"[黑衣忍者甲]",msg:"這裡是紅樹林"}]},jump:[{at:{x:0,y:6},to:"stage01"}]}};}function initScript(){map = stage.map;mapData = stage.mapdata;talkContent = stage.talk;charaList = stage.add;jumpTo = stage.jump;backLayer.removeAllChild();addScene();}
這裡一共有三個指令碼,所以看上去代碼比較多。前面136行都是資料的記錄,只有後面的initScript是用來初始化情境的。
由於我寫這個樣本只是為了娛樂一下,所以沒有寫一句注釋(在下實在是太懶了……),為了方便大家理解,我說一下整個遊戲的製作過程和設計方式。
首先,我們的遊戲主體應該是一像模板樣的東西,資料和這些模板分開,要用到資料時,將資料引入然後然後通過固定的模板實現相同的作用但不同的效果。舉一個例子,假設我們這些程式員有一天穿越到了古代,成為了比程式員還苦的鍊鋼工人(我可沒有詛咒大家啊)……為了方便煉鐵,工廠給我們準備了幾個模子,我們只用將不同的鐵水倒進這個模子,然後等它冷卻,就能打造出材料不同但造型相同的武器(也不知道古代有沒有這種高科技東西)。這樣做的好處是快捷和方便修改。假如我們遇到戰亂的年代,皇帝老兒要咱們在一個月內做1GB這麼多的長槍去抵抗外敵,我們怎麼辦呢??這時如果用到這種方法,那我們就只用不斷得將鐵水倒進模子就可以了。話又說回來,如果模子做得差,那製造出來的東西還是個什麼玩意?
現在我們穿越回來,回到高新的IT時代。現在我們要做的差不多和做兵器是一個原理,因此我們在Main.js裡寫模子,鐵水就交給指令碼處理吧。
如果說看了半天被攪昏了的同學,那就看一下《html5遊戲開發-零基礎開發RPG遊戲-開源講座(四)-遊戲指令碼化&地圖跳轉》一文吧
說了一堆原理性的話,我們不仿聊一下我們的引擎。其實模子做的好不好最關鍵就是看材料,如果我們花比皇宮還貴的錢來修這個模子,那我真心覺得沒這個必要,因此我們應該把模子作得相對簡單。使Main.js中的代碼少的一個重要因素就是用到了lufylegendRPG中的LScene類,這個類非常得帥,用法就不多說了,API看了就知道。
API文檔:http://www.cnblogs.com/yorhom/archive/2013/06/15/3137789.html
差不多就講到這裡吧,各位可以儘可能地發揮特長,利用該引擎製作一款像樣的RPG遊戲。
至於原始碼嘛,可以下載lufylegendRPG-1.0.0,就在解開壓縮包後的rpg_sample檔案夾中。
另外做了一個留言板,歡迎熱愛技術的朋友前來討論:http://www.cnblogs.com/yorhom/archive/2013/04/20/3033235.html
謝謝大家閱讀本文,支援就是最大的鼓勵。
----------------------------------------------------------------
歡迎大家轉載我的文章。
轉載請註明:轉自Yorhom's Game Box
http://blog.csdn.net/yorhomwang
歡迎繼續關注我的部落格