在97年的时候,我在当时国内一个比较热闹的游戏制作的mailist上贴过一篇提议用超大位图做2d游戏场景的文章. 限于当时的机器内存配置和运行速度,及硬盘I/O的缓慢, 我自己都把这个念头杀掉. 因为无论是在 8M 内存下装载上M的位图, 还是动态解码 jpeg 信息, 和实时 load 上百K的数据都是限制.
时至今日, 硬件水平快速发展, 我们这些做 2d 游戏的不得不重提这个方案.毕竟整图做场景有它美术观上独特的诱惑. 在大陆已经发售的古龙群虾传,和正在制作的不灭的传说,剑侠外传,不约而同的都使用了整张位图做为场景,这无疑提高了游戏的视觉冲击力.
但是,据了解/猜测, 国内(包括台湾)生产的这些使用整图做场景的游戏无一不是在进入场景的时候将以类BMP格式的场景信息 Load 如内存.这种方案在单个场景巨大的情况下(640x480x16屏以上)给机器内存带来了很大的负担并且加大的切换场景时的等待时间, 在下看来实为不智
我建议采用以下方案(已经实现验证)将大场景的位图切割成小块如 320x240, 连同场景需要的其他信息打包入特有的地图文件中. 建立一个地图块Cache, 限定上限(32块). 每帧刷新的时候,向 Cache 管理类提交请求, Load & Lock 住需要的加载的地图块(如果游戏 Viewport 为 640x480, 则需要 Lock 9 个 320x240 地图块)根据每次请求的位置变化,对未来的地图块需求做预测,并一起加载地图块每 Lock 一次, 使用次数加1 (Lock 后,再 Unlock 前, 不记重复 Lock)Cache 满后, 除 Lock 的地图块外, 将使用次数最小之地图块请出 Cache
地图块的 Load 使用额外线程管理, 由主线程提出请求, 放入队列.一但不在Cache 中的地图块有 Lock 请求, Load 队列清空, 并优先完成被 Lock 块的读入.
实现要点: 1. Cache 负责协调游戏中所有地图的所有地图块,而不限制于一张地图 原因: 加快场景切换
2. 地图使用 Jpeg 而不用 Bmp 原因: Jpeg 文件小, 减少 I/O 负担, 转嫁到 CPU 负载. 但是多任务运行下,并行运行 CPU 计算任务, 比 I/O 操作和 CPU 运算运行, 要分配均匀的多. 减少辅线程对主线程的停顿影响
3. 辅线程的预读队列处理中,每处理一项, 做少许 Sleep 原因: 同 2
4. 小心多线程编程. 如果以前做的不多尤其小心, 线程的数据安全可能比你想象的要麻烦 原因: 线程的数据交换和通讯, 使数据同步异常关键, 而且容易在编码失误时 造成线程互锁
问: 为什么需要使用这个方案? 用内存镜像文件或者别的方案不是更好吗? 自己设置 Cache 有什么优势?
答: 如果你需要 100 屏的地图, 直接读入内存是没有问题的, 即使你没有 128M 内存, Windows 也可以帮你管理的不错. 但是小心,不要过多以来 Windows 的内存交换管理, 虽然它可以做的很好, 但是还是会让你的机器不堪重负. Windows 并不知道你是在具体在处理什么,针对性的良好设计会节省更多的资源. 而且, 游戏并不是只有地图才会吃掉你巨大的内存, 实际上精灵将吃的更多,如果你的程序不协调一下, 有限的内存会被这两个吃内存大户强来强去最后的结果只能是将你的游戏的内存配置要求提到.而自己管理,可以让它们在自己的地盘协调工作, 大家泾渭分明
读盘时间过长也是一个问题. 当然采用内存镜像文件也很不错. 也许也是个很好的解决方案, 不过就不好采用 jpeg 的优势. 另外我做的项目也不允许. 用 jpeg 都快把光盘撑满了 :) 我可不想让人拿着 4~6CD 换来换去的
好久没有写长点的帖子了. 今天算是对我一周工作总结. 以后做完了别的东西, 再做其他总结. 谢谢耐心看完这么枯燥且充满别字的帖子.
|