×

构建一个2D地图引擎

Kalet Kalet 发表于2009-03-20 12:00:13 浏览567 评论0

抢沙发发表评论

尽管事实上建立一个地图引擎是一件再简单不过事,但是我还是经常收到来自不同的人们的各种邮件,询问我应该怎么样去做,或者是我原来的关于建立一个地图引擎是简单不过的事情的想法是错误的吧,也可能是这些向我求问的人本身很懒吧(你说呢?).因为似乎大家都对这个主题比较感兴趣,这章我将详尽地讲解如何建立一个高的效2D地图引擎.
瓷砖是游戏编程中的专用术语,用来产生2D游戏中的场景,每个瓷砖都对应一种不同的地表结构;比如,海洋,草地,岩石,沙滩.虽然在3D游戏编程中使用了更为先进和生动的场景生成技术,可是运用瓷砖还是能在2D游戏中生成一个较生动和有趣的场景的.相比起来,2D中的这种技术更为容易掌握和应用(而与3D游戏产生的效果是一样的),并且运行得更为快捷.

瓷砖设置方式                                  实际要绘制的总瓷砖数         备注
 

构建一个2D地图引擎
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 _构建一个2D地图引擎
_ 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.构建一个2D地图引擎
使用瓷砖的另外一个方面是实际绘制它们.最重要的事是要保证它们之间是无缝拼合的,你至少不能看到明显的缝隙,这就是人们常说的"无缝拼接",



群贤毕至

访客