为游戏保存大量数据



因此,我正在用C++设计一款具有大量数据的2D游戏——基本上,它具有随机生成的块状地形(以一个非常大的字节数组的形式),非常像Terraria的风格,还需要为怪物(以及其他各种游戏对象)保存状态。当玩家四处奔跑时,游戏世界的部分将被加载/保存到磁盘上,从而形成一个无限扩展的游戏世界(类似于《我的世界》)。

将所有内容保存到磁盘的最佳选项是什么?我最关心的是效率(所以用户永远不必等待内容加载),但易用性和可维护性紧随其后。我非常熟悉Minecraft的保存方法,每个"Chunk"都有一个单独的文件,但我想知道——我应该像Minecraft一样指定自己的文件,还是使用数据库?还有什么其他的可能性?如果我使用一个文件,我会通过向操作系统请求原始访问并亲自处理(就像数据库一样)来显著提高性能吗?

此外,我希望能够将项目从PC移植到Mac和控制台——单个平台的替代方案很好,我只需要根据平台交换方法。

谢谢!

数据库的目的是加速复杂的搜索。您没有进行任何搜索;你有一块数据需要进入内存。对于这项任务,数据库对您来说毫无价值。

你真正需要的取决于你谈论的数据量和你想要的特定平台。你似乎在谈论一个2D游戏,所以区块不可能有那么大。常规的C或C++文件IO函数可能就足够了。最糟糕的情况是,您可能不得不将它们粘在一个线程中以进行异步文件IO和处理。

真的,开始做显而易见的事情吧。如果出现问题,请尝试使用简单的线程结构使其异步。你可能不需要走得太远。

与组织依赖文件系统相比,单个文件会更干净,占用更少的物理磁盘空间。只需在文件的开头维护一个偏移量表,就可以链接到每个块。

至于压缩,应用游程编码肯定会缩小文件大小,如果它像《我的世界》一样,你会有很多相同的块。另外,它将在使用盘片驱动器的计算机上更快地加载,因为几个字节可以相当于数千个块,而不必为每个块读取一个字节。这里有一个有效游程长度编码的快速提示:使用命令字节,比如0x00。所有其他字节都与一个块相关联,但命令字节表示信息的非块位。传统的行程编码如下所示:

Source: AAAABBBBBBBCDDDEFA
Destination: 0x0441074201430344014501460161
Plaintext: .A.B.C.D.E.F.A

使用命令字节,省略会增加大小的序列:

Source: AAAABBBBBBBCDDDEFA
Destination: 0x00044100074243444444454641.
Plaintext: ..A..BCDDDEFA

这在数据的"大理石花纹"部分具有明显的优势。

还有一件事,我建议您使用一个类似于midi格式的数字存储系统,尽管是小端序格式。为了节省你在谷歌上的搜索,它真正意味着你要为存储数字的每个字节牺牲一点。如果设置了第8位,则意味着数字中还有另一个字节,并且它级联。示例:

Storing: 65
Stored as: 0x41 (01000001) //The eighth bit is not set, so this number only occupies 7 bits.
Storing: 192
Stored as: 0xC081 (11000000 10000001) //The eighth bit of the first byte is set, so the following byte is part of the number. The second byte doesn't have the eighth bit set, so the number ends there.
Storing: 612453
Stored as: 0x72D825 (11100101 1011000 00100101) //The eighth bit of the first two bytes are set, and the third is not, so this number occupies 3 bytes.

我希望我能提供一些见解。

根据我的经验,这确实取决于很多因素。我的团队有一个将数百甚至数千个文件保存到数据库的系统,性能得到了提高。这些文件很小,因此与等待磁盘驱动器启动或操作系统将文件系统导航到每个单独文件的延迟相比,读取和写入时间很短。

如果你有数千个小于4kB页面的文件,我会选择数据库。如果文件大于此值,则使用文件。数据库对吞吐量没有帮助,只对延迟有帮助。

最新更新