魔獸爭霸自動地圖元件的繪製原理

魔獸爭霸自動地圖元件的繪製原理

序:

本文主要介紹一種簡單高效的自動地圖元件的繪製方法,基本的原理是基於CodeProject的作者爲Colin Vella的一篇文章:http://www.codeproject.com/KB/game/Autotiles_Algorithm.aspx#_comments 該文章介紹的方法非常簡單,而且很高效。本文會先講述此方法,然後在此方法的基礎上,介紹魔獸爭霸的自動地圖元件的繪製原理,因爲其實這2者的原理是一樣的,但方法稍有不同。

1.基本原理

對於自動地圖元件,我們可以這樣理解,它實際上是一種地形分割器,例如

岸邊 -- 水和陸地的分割;

牆壁 -- 室內和室外的分割。

1

那麼我們就可以用01分別來代表兩種地形了,我們將一個tile分成4個角,每個角都可能是兩種地形的其中一種(即可以是0,也可以是1)。

這樣我們用一個4位的數字b3b2b1b0表示一個tile,其中每一位表示一個角的地形,如下圖


2

這樣4個角總共有16種情況,分別是以下16種,如下圖,我們將藍色部分想象成水,黃色部分想象成陸地,而兩者間的黑線想象成岸邊


3

在實際繪製過程中,我們就是用這16種情況類拼接地圖的。

2.自動地圖元件的規格

上面圖3就是此方法使用的地圖元件的規格,注意此方法使用的自動地圖元件的規則與RMXP的規格並不一樣,在某種意義上說,RMXP的地圖元件的精度要高一點,這點會在後續文章中給出分析。

在圖3中,我們故意將原件按其對應數字的大小來排序,也就是說0000排在第一,0001排在第二,1111排在最後。這樣就可以很方便地根據tile的數值對應到其實際貼圖了,用如下方法

int tileNumber = tileMap[row][col];
Rect srcRect(tileNumber * tileWidth, 0, tileWidth, tileHeight);

3.繪製算法

繪製的算法非常簡單,反而是原文講得比較繞口。如下圖,我們打算在位置4繪製地圖元件,此時我們只需將位置4以及它周圍共16個小格填爲1即可。如下圖:


4

注意一點,我們只是將上圖紅色方框內的16個小格填爲1而已,並不改動方框外的格的內容。例如左上角,我們假設其當前值是0110,那麼改動後變成1110

算法要注意的地方是,在地圖的邊緣時,要考慮繪製位置的旁邊是否有tile,例如在(0,0)位置繪製時,0,1,2,3,6格子都是不存在的。

繪製的代碼如下:rc分別代表要繪製的行和列號,easyMap是二維數組,保存了所有tileMAPROWMAPCOL分別是地圖的行數和列數。

// 將中心點周圍的16個小格填爲1

if (r > 0)
{
    if (c > 0) easyMap[r - 1][c - 1] |= 0x8;    // 1000
    easyMap[r - 1][c] |= 0xC;   // 1100
    if (c < MAPCOL - 1) easyMap[r - 1][c + 1] |= 0x4;   // 0100
}

if (c > 0) easyMap[r][c - 1] |= 0xA;    // 1010
easyMap[r][c] |= 0xF;   // 1111
if (c < MAPCOL - 1) easyMap[r][c + 1] |= 0x5;   // 0101

if (r < MAPROW - 1)
{
    if (c > 0) easyMap[r + 1][c - 1] |= 0x2;    // 0010
    easyMap[r + 1][c] |= 0x3;   // 0011
    if (c < MAPCOL - 1) easyMap[r + 1][c + 1] |= 0x1;   // 0001
}

消除的過程是繪製的反過程,也就是將填爲116個小格填爲0即可

// 將中心點周圍的16個小格填爲0

if (r > 0)
{
    if (c > 0) easyMap[r - 1][c - 1] &= ~0x8;   // 0111
    easyMap[r - 1][c] &= ~0xC;  // 0011
    if (c < MAPCOL - 1) easyMap[r - 1][c + 1] &= ~0x4;  // 1011
}

if (c > 0) easyMap[r][c - 1] &= ~0xA;   // 0101
easyMap[r][c] &= ~0xF;  // 0000
if (c < MAPCOL - 1) easyMap[r][c + 1] &= ~0x5;   // 1010

if (r < MAPROW - 1)
{
    if (c > 0) easyMap[r + 1][c - 1] &= ~0x2;   // 1101
    easyMap[r + 1][c] &= ~0x3;  // 1100
    if (c < MAPCOL - 1) easyMap[r + 1][c + 1] &= ~0x1;   // 1110
}

4.魔獸爭霸的自動地圖繪製

如果你沒用過魔獸爭霸的地圖編輯器,那麼你可以在魔獸爭霸的遊戲目錄下找到它,World Editor.exe

打開它默認出現的就是編輯地形的模式,可以看到它的地形編輯與RMXP的不同是,它是以頂點來定位的,而不是RMXP的以tile來定位的。如下圖


5

要繪製出魔獸爭霸的地圖編輯器的效果,用上面的算法即可,不過需稍作修改。如下圖,我們打算在中心頂點位置繪製地圖元件,此時我們只需將該頂點附近4個小格填爲1即可,也就是將下圖紅色方框內的小格填爲1


6

5.共性

我們將魔獸爭霸地圖編輯器的繪製形狀改爲正方形,尺寸改爲2,如下圖


7

這圖是不是有點時曾相識呢,就是跟上述填16格的算法的區域基本一樣。此時我們可以得知,此算法對繪製區域有一個隱性要求,就是繪製區域不能設定爲剛好是整數個方格。試想一下,參考圖4,如果在繪製時,我們僅將中心的4個小格填爲1會出現什麼情況?情況就是我們只能繪製出00001111兩種地形了,魔獸爭霸的地圖編輯器也一樣,你可以改一下繪製區域的尺寸,不管是什麼尺寸,都不會出現上面所說的情況。

6.實現

具體的實現代碼可以從下面地方下載,是用的HGE引擎編寫的。如果你沒用過,可以在這裏下載HGE並學習:http://hge.relishgames.com/ 

下面是程序的截圖


代碼下載地址:http://download.csdn.net/detail/gouki04/4025467 

項目使用VS2008寫的,打開後直接生成解決方案即可。裏面包含2個項目,分別是上面所說的2種方法,生成成功後可直接運行,操作爲鼠標左鍵繪製,右鍵清除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章