構建一個2D地圖引擎

http://216.5.163.53/DirectX4VB/Tutorials/DirectX7/DD_Tiles.asp

儘管事實上建立一個地圖引擎是一件再簡單不過事,但是我還是經常收到來自不同的人們的各種郵件,詢問我應該怎麼樣去做,或者是我原來的關於建立一個地圖引擎是簡單不過的事情的想法是錯誤的吧,也可能是這些向我求問的人本身很懶吧(你說呢?).因爲似乎大家都對這個主題比較感興趣,這章我將詳盡地講解如何建立一個高的效2D地圖引擎.

瓷磚是遊戲編程中的專用術語,用來產生2D遊戲中的場景,每個瓷磚都對應一種不同的地表結構;比如,海洋,草地,岩石,沙灘.雖然在3D遊戲編程中使用了更爲先進和生動的場景生成技術,可是運用瓷磚還是能在2D遊戲中生成一個較生動和有趣的場景的.相比起來,2D中的這種技術更爲容易掌握和應用(而與3D遊戲產生的效果是一樣的),並且運行得更爲快捷.

其實在所有的工作中,最主要的考慮因素還是瓷磚的大小.如果瓷磚太大,用它來表現的地表可能就不細緻,反之如果太小,遊戲速度將因此而拖慢(因爲同樣大小的地面,瓷磚小將使用過多數量的瓷磚),並且考慮到降低問題本身的複雜性的方面,用這些瓷磚組合起來的地圖大小要正好是屏幕的倍數.比如,X數量的瓷磚總寬度剛好與y個屏幕的寬度相等.下面提供了一張簡單的對應表:

屏幕大小 瓷磚設置方式                                  實際要繪製的總瓷磚數         備註

640x480  5x5      128 tiles wide, 96 tiles high =      12,288 tiles to be drawn     Red
         10x10    64 tiles wide, 48 tiles high =       3062 tiles to be drawn       Green 
         16x16    40 tiles wide, 30 tiles high =       1200 tiles to be drawn       Green 
         32x32    20 tiles wide, 15 tiles high =       300 tiles to be drawn        Yellow
 
800x600  5x5      160 tiles wide, 120 tiles high =     19,200 tiles to be drawn     Red
         10x10    80 tiles wide, 60 tiles high =       4800 tiles to be drawn       Green
         16x16    50 tiles wide, 37.5 tiles high =     1850 tiles to be drawn       Green
         32x32    25 tiles wide, 18.75 tiles high =    468 tiles to be drawn        Yellow

1024x768 5x5      204.8 tiles wide, 153.6 tiles high = 31,212 tiles to be drawn     Red
         10x10    102.4 tiles wide, 76.8 tiles high =  7752 tiles to be drawn       Red
         16x16    64 tiles wide, 48 tile high =        3062 tiles to be drawn       Green
         32x32    32 tiles wide, 24 tiles high =       768 tiles to be drawn        Yellow

注意到在某些解決方法中有些瓷磚的組合並不與屏幕大小真正切合;這表明你將需要一些額外的像素來填充這些地圖(瓷磚的組合)邊緣空出來的屏幕部分.我在上面的表中已經用"Red"註明這些需要避免出現空白的解決方法(與接下來的"Green,Yellow"組成一個"備註"項),用"Green"註明了那些合適的解決方法,用"Yellow"註明了那些需要在必要的時候才應該使用的解決方法.

如果你不打算用上面這些解決方法中的任何一種或者在你使用DX的窗口模式下的情況下,上面這張表對你是沒有意義的;但是大體上這些解決方法與其它解決方法都是一樣的(都按同一個公式來計算),都遵循一個通用的原則:
只有那些瓷磚數在1000-5000之間的解決方法都是可選的,多於這個數目的瓷磚數將會使要形成的地圖引擎的運行速度打折扣.

實際的組合瓷磚形成地圖的方法很簡單;這裏有介紹二種主要用到的方法:

程序運行時,組合瓷磚生成地圖內容到一個單獨的繪圖頁上-因此這種方法只涉及到一個生成過程.如果採用這種方法,以上提供的表項將完全無一可用.並且,採用這種方法可能會對接下來的Z軸轉換和遮蓋處理帶來困難.

程序運行時,在一個循環裏生成地圖.這會在很大程序上降低幀的播放速率(fps,frame per second),在快一點的機器上會更明顯.但是在一些優化工作後可以達到一個合理的播放速率.這種方法允許你輕鬆地生成動畫,進行混合處理,透明處理.

我們在接下來的程序中將使用一個簡單的循環來組合生成地圖;以下實現的組合生成地圖的過程可以說是在當前程序運行時完成的,也可以說是在文章最後面鏈接的那個程序中進行的:

Sub RenderMap(NumTilesX as integer,NumTilesY as integer, TileWidth as integer,TileHeight as integer _
_ TileSourcesurf as DirectDrawSurface7, TileDestSurf as DirectDrawSurface7)

Dim X as integer, Y as integer, r as RECT, retVal as long

For X = 0 to NumTilesX
For Y = 0 to NumTilesY
'Create our Rectangle.
r.Left = 'Left coordinate for Tile on source surface
r.Top = 'Top coordinate for Tile on Destination surface
r.Right = r.Left + TileWidth
r.Bottom = r.Top + TileHeight
'This is where we copy the tile from the source to the destination
retVal = TileDestSurf.BltFast(int(X * TileWidth), int(Y * TileHeight), TileSourceSurf, r, DDBLTFAST_WAIT)
Next Y
Next X

End Sub 
 
以上函數將完成一個生成地圖的過程.我們可以對它作一些改變以加快地圖在每一個循環裏被生成的速度.

Remove the Multiplications. There are 6 different maths functions in the above code. This could possibly be cut down. Using Multiplication and/or division is quite costly on a loop basis. The easiest way that this can be done is by using a lookup table. On the first loop we calculate ALL the coordinates and store them in an array, then on subsequent loops we just look at this array and the calculation will be done; this is known as a lookup table. 
移除乘法運算(而改用加法或使用其它辦法).以上的子程序用到了6個不同的數學函數.實際上這可以被精簡.使用乘法運算和邏輯運算將在一個循環的主體裏花費不少的系統佔用.最直觀和簡單的方法是使用一個對照表.
Only Draw if necessary. This is the simplest way of speeding things up. The Fruitworld game does this, all the tiles are represented by a number in an array, if this array has changed since the last loop it will draw it, otherwise it moves onto the next iteration. This can easily be combined with the lookup table suggested above. 
只在需要繪製的時候進行實際的繪製.這是最讓人信服的提速的方法了.遊戲"水果世界"的源代碼使用了這個方法,所有的瓷磚都對應一個索引值被存放在一個數組裏以供調用,
The other aspect of using tiles is actually drawing them. The most important thing is that they join together perfectly - and you cant see the joins between them, this is called a seamless pattern, and you can use PaintShop Pro to generate one for you. The next aspect is what they look like; although detail is important, there is a fine line. Assuming that you are drawing generic landscape (Grass, Sand, Water) - you dont want the user's eye to be focused on it; the grass, water and sand are the background, not the foreground.
使用瓷磚的另外一個方面是實際繪製它們.最重要的事是要保證它們之間是無縫拼合的,你至少不能看到明顯的縫隙,這就是人們常說的"無縫拼接",

發佈了11 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章