一,話說天下大事
前不久看到lufy的博客上,有一位朋友想要一個RPG游戲引擎,出於興趣准備動手做一做。由於我研究lufylegend有一段時間了,對它有一定的依賴性,因此就准備將這個引擎基於lufylegend。暫時命名為lufylegendRPG。畢竟基於lufylegend,如果名稱中不加上lufylegend這幾個字的話,有點說不通啊。。。最近發布了0.1.0版,但是不理想,連一慣都是鼓勵和贊賞我的lufy老先生都是出於真心的表示不滿意。想了解0.1.0版的朋友可以看看這里(其實最好別看,因為1.0在用法上做了很大的調整):
http://blog.csdn.net/yorhomwang/article/details/8738733
於是我不得不重新來開發它。首先想到了地圖類,今天就來實現一下。
我們的地圖不應該是一張大地圖,而是用小地圖拼接而成,這樣方便我們修改地圖。
這樣的話我們需要許多地圖塊的圖片,通常我們把它們放在一張上。我們就用lufy老先生blog上一張圖片作為例子,給大家看看這種裝滿小地圖的大圖是什么樣的:
我們要完成的效果是什么樣的呢?我把它放在這里,完成后看看實現度到底有多少:
二,如何實現
准備工作:
首先你需要下載lufylegend,最新版本是1.7.5,用1.7.3都行。
下載地址:http://lufylegend.com/lufylegend
上面有它的API和論壇,可以看看。
另外推薦一本相關圖書,lufy寫的,叫《HTML5 Canvas游戲開發實戰》。用於學習基礎和了解開發技巧還是不錯的。其中還有一些很不錯的js技術指導。值得一看。
書籍介紹:http://lufylegend.com/book/view/1
開始編寫
由於lufylegend做的比較完美,那么我們封裝起來就比較簡單了。看看LTileMap完整構造器:
function LTileMap(data,img,width,height){ var s = this; base(s,LSprite,[]); s.x = 0; s.y = 0; s.mapData = data; s.imgData = img; if(!width){ var wbitmap = new LBitmapData(s.imgData); s.partWidth = wbitmap.image.width; }else{ s.partWidth = width; } if(!height){ var hbitmap = new LBitmapData(s.imgData); s.partHeight = hbitmap.image.height; }else{ s.partHeight = height; } s.onshow(); }
首先為了減少引擎的大小,我們把變量s和this等起來,下面用到this的地方就都能用s來實現了。
※lufy大神最近提示我:“把變量s和this等起來是為了防止this的指向發生變化,並非單一減少引擎的大小。因為this的指向不一定一直指向當前函數的。”在此再次感謝lufy的支持。
首先我們讓它繼承LSprite,這樣如果我們改變x和y屬性后就可以直接變換位置了。再追加兩個屬性:mapData和imgData。
mapData是通過data參數賦值的,data的賦值應該是一個二維數組,格式如下:
[18,18,18,18,18,18,18,18,18,18,18,18,55,55,18], [18,18,18,17,17,17,17,17,17,17,17,17,55,55,18], [18,18,17,17,17,17,18,18,17,17,17,17,55,55,18], [18,17,17,17,18,18,18,18,18,17,17,55,55,17,18], [18,17,17,18,22,23,23,23,24,18,17,55,55,17,18], [18,17,17,18,25,28,26,79,27,18,55,55,17,17,18], [18,17,17,17,17,10,11,12,18,18,55,55,17,17,18], [18,18,17,17,10,16,16,16,11,55,55,17,17,17,18], [18,18,17,17,77,16,16,16,16,21,21,17,17,17,18], [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18]
它裝載着地圖塊的樣式,18對應的圖塊和55對應的圖塊是不一樣的。后面我們會細講。
imgData顧名思義,它是一個裝圖片的容器。
還有兩個參數,它們是用來表示地圖快的高度和寬度的。例如每張地圖塊是32*42的,那么就要將width設為32,height設為42。這樣的話就會將裝滿地圖塊的圖片分成小地圖。例如我們把上面那張圖片分成每個小地圖塊是32*32的,也就是說width設為32,height也設為32,那么就呈現現以下的形式:
(以上圖片我直接用了lufy博客里的圖片)這時你可以看看18和55所對應的是什么。18是一棵樹,而55對應的是水,因此我們就做到了讓每張地圖塊顯示得不同。
接下來是onshow方法:
LTileMap.prototype.onshow = function(){ var s = this; var mapdata = s.mapData; var partWidth = s.partWidth; var partHeight = s.partHeight; var i,j; var index,indexY,indexX; var bitmapdata,bitmap; for(i=0;i<mapdata.length;i++){ for(j=0;j<mapdata[0].length;j++){ index = mapdata[i][j]; indexY = Math.floor(index/mapdata.length); indexX = index - indexY*mapdata.length; bitmapdata = new LBitmapData(s.imgData,indexX*partWidth,indexY*partHeight,partWidth,partHeight); bitmap = new LBitmap(bitmapdata); bitmap.x = j*partWidth + s.x; bitmap.y = i*partHeight + s.y; s.addChild(bitmap); } } }
它的功能很簡單,就是畫出地圖。其中的邏輯都很簡單。主要是這里:
for(i=0;i<mapdata.length;i++){ for(j=0;j<mapdata[0].length;j++){ index = mapdata[i][j]; indexY = Math.floor(index/mapdata.length); indexX = index - indexY*mapdata.length; bitmapdata = new LBitmapData(s.imgData,indexX*partWidth,indexY*partHeight,partWidth,partHeight); bitmap = new LBitmap(bitmapdata); bitmap.x = j*partWidth + s.x; bitmap.y = i*partHeight + s.y; s.addChild(bitmap); } }
這一段代碼是畫出地圖的核心,首先它遍歷了地圖數組,然后每遍歷一個就畫一張,然后加到自身中。由於自身是繼承自LSprite,所當地圖被加到自身中時,再將自身加到底層或者其他Sprite中時,整個截面就會顯示。
over,很簡單是不是?實現后我們怎么用它呢?看以下代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>LTileMap</title> <script type="text/javascript" src="../lufylegend-1.7.3.min.js"></script> <script type="text/javascript" src="../lufylegendrpg-1.0.0.min.js"></script> <script> init(30,"legend",480,320,main); LGlobal.setDebug(true); var backLayer,loadingLayer; var map; var loadData = [ {name:"map",path:"./map.jpg"} ]; var imglist = []; var mapData = [ [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18], [18,18,18,17,17,17,17,17,17,17,17,17,55,55,18], [18,18,17,17,17,17,18,18,17,17,17,17,55,55,18], [18,17,17,17,18,18,18,18,18,17,17,55,55,17,18], [18,17,17,18,22,23,23,23,24,18,17,55,55,17,18], [18,17,17,18,25,28,26,79,27,18,55,55,17,17,18], [18,17,17,17,17,10,11,12,18,18,55,55,17,17,18], [18,18,17,17,10,16,16,16,11,55,55,17,17,17,18], [18,18,17,17,77,16,16,16,16,21,21,17,17,17,18], [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18] ]; function main(){ //加入進度條 loadingLayer = new LoadingSample1(); addChild(loadingLayer); //加載圖片並顯示進度 LLoadManage.load( loadData, function(progress){ loadingLayer.setProgress(progress); }, gameInit ); } function gameInit(result){ removeChild(loadingLayer); imglist = result; //初始化層 backLayer = new LSprite(); addChild(backLayer); //加入地圖 addMap(); } function addMap(){ map = new LTileMap(mapData,imglist["map"],32,32); backLayer.addChild(map); } </script> </head> <body> <div id="legend"></div> </body> </html>
運行代碼得到如下效果:
為了防止大家以為我ps圖片,那我就不仿把測試鏈接給出,大家自己看吧。
測試地址:http://www.cnblogs.com/yorhom/articles/3063759.html
代碼很少,可以自己復制粘貼下來看看。哈!