如何制作一款HTML5 RPG游戲引擎——第一篇,地圖類的實現


一,話說天下大事

前不久看到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

代碼很少,可以自己復制粘貼下來看看。哈!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM