无限大小的地图处理


  通常的 RPG 游戏场景的大小都是有一定的限制的, 这取决于内存的大小等诸多因素. 大多的 RPG 在场景切换间, 都有取盘的操作, 将内存中的场景更替. 而云风一直想做一个Engine 能管理无限大小的地图. 当然, 将所有的场景读入虚存是不可取的, 虽然 386 以上机器都可以管理 4G 的虚拟内存, 但是用户的硬盘空间是有限的, 而且处理虚拟内存也较慢. 我们应该自己来设计专门的算法.

  具体的思路, 我在斜视角引擎设计:地表的数据组织及滚屏一节中提过. 不过在后来的实际设计中也碰到许多问题. 这次去北京的路上, 无聊的火车中, 我仔细推算了数据处理数量, 分析可行性, 得出了比较好的方案.

地图示例(12,331 字节)   来看看左图, 将地图分为块, 每一块的大小为 1/4 屏幕大. 屏后缓冲的大小为 9 块(被标上 1~9). 如图, 当屏幕显示在这九块内时(黄色框表示屏幕), 左上角顶点落在 1 号块. 这里我们将 1 号块再分成 4 个区域, 甲乙丙丁. 当落在丁域, 内存中还应该保证有 A,B,C,D,E,F,G 7 块在内存中. 这样能使左上角顶点从丁域移出屏后缓冲, 新的屏后缓冲能迅速建立起来. 同理, 当顶点在甲区域, 对应的 7 块为屏后缓冲的左面和上面 7 块(依此类推). 现在我们来计算一下每个地图块的内存消耗量: 如果游戏运行在 640x480x16bit 下, 一个块的大小为 320x240x2Bytes=154K, 如果算上可能的遮挡, 平均数据量应该不超过这个数字的两倍, 我们简单的计算为 300K. 内存中永远存放 16 个块 (4个屏幕大小) 的图形数据量, 300K x 16= 4.8M,应该在物理内存可以承受的范围内. 当移动屏幕, 左顶点从一个区域移动到另一个区域时, 变化了 7 个图块(计为 2.1M) 这是要经过 I/O 交换的, 才是瓶颈所在. 利用 Win9x 的多任务特性, 我们可以为游戏开两个线程, 除主线程外, 另一线程专门负责加载屏后缓冲周边的动态更替数据. 这最多达 2.1M 的数据(由于数据可以采用压缩, 大多数情况只有其的一半, 1M 左右) 的更新周期就是屏幕左上角顶点斜向移出一个小区域的时间, (横向移出只需要更新 3 块, 900K).如果我们设定游戏为 25 fps, 每次滚屏移动 1 到 2 点, 一个小区域大小为 160x120, 斜向移出的最短时间在 100 帧, 即 4 秒左右. 我们的问题就是要在 4 秒周期内同外存交换 2.1M 的数据, 同时不间断游戏. 从目前的 CD-ROM 的速度来看, 理论上是满足要求的 ;-) 但这里应该注意, Win9x 的多任务特性不是很稳定, 我们只有将 I/O 操作尽量的分散才可以使两个线程运作均匀. 所以将游戏作成 Tile Base, 每个图块被切割成数十个 Tile, 分多步加载是对游戏的流畅是非常有利的.

  OK, 云风将在近期内为本文再配上演示程序,作为验证,请期待.

[相关系列文章]