斜视角图形引擎的设计

精灵的内存消耗

[上篇:精灵影子处理(实时篇)][下篇:待续...]

  如果实践过写 Diablo too 的引擎,将发现内存永远是困扰我们的大问题. 其中景物背景很直观的消耗了大量的内存,但是真正吃内存的大户却在于会动的部分, 比如精灵.

  这里简单的计算一下, 一张 80*96 的高彩图片, 占内存 80*96*2=15K. 如果我们在游戏中采用 8 个方向, 再以人物行走为例, 一般 9 帧左右可以让人满意, 那么, 整组画面将消耗内存 15x8x9k=1080K. 初看这个数字是否要吓你一跳呢? 除了行走, 为了生动, 往往在人物站立时也需要一组动画, 再加上打斗等, 这个内存的消耗就成了最让程序员头痛的事情.

  简单的解决方法是使用调色板, 在显示时转化为高彩. 这样一个调色板虽然 多占 512 字节, 但整个画面的内存消耗可以减半. (我更羡慕 BILLZARD 的本事, 能将 256 色模式用的出神入化, 省了程序的不少心思) 再者简单的将透明色压缩掉, 即 RLE 压缩. 还有什么方法呢? 我认为一个是硬的, 一个是软的. 硬指硬技术, 从压缩上入手, 前段时间我在考虑帧间压缩, 以记录动画人物各帧之间的区别来 减少记录每帧图的巨大内存消耗, 效果不是太好, 我的方法是: 完整记录第一帧的图形, 在记录第2和第1帧的区别, 第 3 和第 2 的... 第 n 帧和第 1 帧区别. 运行时, 因为动画永远是循序循环显示, 所以只需要在内存中保留一个缓冲区保留当帧的图象. 可惜如果屏幕上如果有多个相同人物, 由于他们显示的帧不同而要开多个缓冲, 效果就适得其反了 :-( 而若记录每一帧和第一帧的区别, 则每次都要先画第一帧再画其他帧, 速度上大打折扣. 而且本身简单的帧间压缩效率并不高,不知道能否找到更好的算法. 当然还可以减少调色板的数目, 改用 64 色就可以用 2 个字节描述 3 个点, 方法都是人想的, 如果大家想出好方法, 不妨拿出来大家讨论一下; 我所说的软方法指在不为人注意的地方省掉一些画面. 比如 Diablo, 人物在行走的时候能够有 8 个方向, 但是却只能以 4 个方向站立, 这真是设计的很巧妙.

  如前所述, 我们还需要考虑轮廓, 影子等其它信息. 无论从内存还是速度上考虑 都需要建立专门的文件格式. 我只简单谈下自己构思的实现方案, 实际还没有写成代码, 所以并不详尽. 通常的 RLE 压缩是记录重复点的个数再记录点的颜色, 这里我们只压缩点透明色, 故而可以不记录被重复点的颜色. 那么可以如下描述图形信息:


透明点的计数 连续色点的计数 色点信息... 透明点的计数 连续色点的计数 色点信息...
如果从效率考虑, 我们应该使用长整数操作为上, PC 上数据对齐有利于速度, 色点的信息可以是 4 个一组, 但计数却是单字节, 所以应当将计数全部移到 数据的前面. 至于每组连续的色点信息, 应该保证是 4 个一组, 便于操作. 至于实际 4 个一组分剩下的, 可以在轮廓描述时单独描述;

  关于轮廓信息的描述, 如前文, 我们将透明级别分做 3 级, 加上不透明一级 (即刚才分剩落单的点) 一共是 4 级, 正好占用 2 个 bit. 我以两个字节描述一个点, 一个为颜色值, 另一字节高两位描述透明级别, 低六位描述横向位移. 当颜色值为 0 即透明色时, 作为特殊标志, 改变另一字节的含义, 或表示换行, 或因为六位不够描述横向位移而下对字节继续描述这个点的信息.

  影子信息比较简单, 没有颜色值, 只是些横线, 记录下起始点即可, 这里略去不详细描述.

  关于我自己的引擎这部分的具体数据结构, 要等代码写完后才能抄到这里. 大家见谅. 我想一点是永远重要的, 就是要节省每一字节,考虑每一个时钟周期, 并在其中找到均衡点. 游戏程序设计的魅力在于此, 我们要努力求精, 才能赶上国外的前辈.