会员: 密码:  免费注册 | 忘记密码 | 会员登录 网页功能: 加入收藏 设为首页 网站搜索  
游戏开发 > 程序设计 > 数据管理
关于图形数据在内存存放方式的思考
发表日期:2006-08-23 20:59:37作者: 出处:  

  搞游戏设计,原来我一直以为,在DirectDraw下面使用Surface存放图形数据(特别是地图元素图形数据)就可以了。使用的时候,直接把图素Blit到BackSurface里面去。但是现在看来,这样其实是一种很不明智的做法。
  现在的游戏设计大多数使用的是斜视角的的地图图素。见下图:



这些图素是我从《帝国时代》里面挖出来打算用于《中国海军——铁翼横空》演示版的。从上图可以看出,地图的图素是一个一个的菱形小方块,如果直接放在Surface里面去,是必要占用绿色方格那么大的空间,实际上,方格里面黑色的部分在地图里面是透明的,也就是没有用到的部分,这样一来,一个菱形的图素占用的Surface要比他的实际面积大一倍。在游戏重要用到的图素远不止这么一些,每个图素浪费一点内存,总的内存浪费实在可观。即使是对于一个小游戏,这样的浪费也有可能严重的影响到游戏的速度。
  另外一个问题是,我们现在使用的地图图素是256色的,但是我们现在开始编写的游戏却已经基本上转向了65536色,这样,如果我们把这样的图素放入16位的Surface中去,浪费的内存更加可观:足足是原来图素大小的4倍!这样我们必须要找到一种方法来阻止或者说减小这种浪费,这样对我们的游戏运行速度也有很大的帮助(因为这样一来,大大减少了需要传输的数据量。
  怎样做到这一点呢?
  RLE压缩。RLE压缩是一种行压缩算法,他的工作原理是,如果一行里面连续有几个相同的数据,他就把他表示成这样的形式:
  [N]X
其中,N是表示连续数据的个数,X表示连续的数据。
  实际上,我们在内存里面使用的压缩算法远远没有这么复杂,我们所要做的只是:把图素方格内的黑色部分看作是空格,我们只要把空格压缩掉就可以了。这实际上是一种不完全的RLE压缩。我们来看一下它对内存节省的效率:(图素的宽高分别是:62,32像素)
  未压缩:
    占用空间=62*32*1(字节/8位)=1984字节

  压缩:当然我们首先要定义一个数据结构如下:
  typedef struct tagRLEBitMap{
    WORD width,height;
    void lpData;
    }RLEBitMap;
  typedef struct tagRLELine{
    WORD start;
    BYTE * data;
    void * NextLine;
    }RLELine;
然后在每行数据之前加上一个Word来表示这以行数据开始的地方,结尾加上一个指针来表示狭义行数据存放的地方。这样,我们每行需要6个字节来代替空格。以一个62*32的图素为例:
    占用空间=(1984/2)+6*32+sizeof(RLEBitMap)
        =992+192+8=1192字节
实际上,对于这种压缩算法,面积越大,空格越多(当然是连续空格),效率越高,越接近50%。但是对于过小的图素,还是不要压缩的好,以免反而浪费空间。我个人的看法,每行数据小于32个像素,就不要压缩了(这个数值不是计算出来的,我懒得算了。)其实更简单一点的方法是使用一个RLELine数组,我就不说了。实际使用时,很可能压缩的和不压缩的同时存在,我们还要做一个标记来确定图素是否压缩。
  另外,把256色的图素数据如此保存,对于使用16位色怎么办呢?很简单,使用一个16位的调色版就行了,使用的时候,直接把改数据对应的调色版值放上去,不过这样带来的另外一个问题是,我们不能使用DirectDraw的Blit函数,而要另外写我们自己的Blit了。不过这已经不属于本文要讨论的问题。

返回顶部】 【打印本页】 【关闭窗口

关于我们 / 给我留言 / 版权举报 / 意见建议 / 网站编程QQ群   
Copyright ©2003- 2024 Lihuasoft.net webmaster(at)lihuasoft.net 加载时间 0.00255