2012-03-01 59 views
0

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

将所有内容保存到磁盘的最佳选择是什么?我最关心的是效率(因此用户不必等待内容加载),但易用性和可维护性紧随其后。我对Minecraft的保存方法非常熟悉,对每个“块”都有一个单独的文件,但我想知道 - 我应该指定我自己的文件,如Minecraft还是使用数据库?还有什么其他的可能性?如果我使用一个文件,通过向操作系统请求原始访问并处理自己(如同数据库一样),我可以获得显着的性能提升吗?

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

谢谢!

+2

这可能是[gamedev.se](http://gamedev.stackexchange.com/)更好的问题。 – 2012-03-01 04:34:16

回答

1

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

就压缩而言,应用运行长度编码会明显缩小文件大小,如果它与Minecraft类似,则会依次有很多相同的块。作为奖励,它将在使用拼盘驱动器的计算机上加载速度更快,因为几个字节可以等同于数千个块,而不必为每个块读取一个字节。下面是一个有效的游程编码的快速提示:使用一个命令字节,比如说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. 

我希望我帮忙提供一些见解。

+0

太棒了,这真的很有用。我以前从来没有搞错过编码,但我理解基础知识。我将不得不在Google上做一些搜索,以及拼盘驱动器。我可能会将MIDI风格的编码用于“特殊”块(比如Minecraft中的TileEntities--比如说我想要一个包含物品的胸部)。谢谢! – Philip 2012-03-01 05:35:37

+0

没问题。我以前用一个额外的字节存储数字长度的格式。这很简单,但对于占用7个字节或更少的数字,效率并不高,并且我从不使用大于4个字节的数字。当我查阅midi格式时,我很高兴用这种巧妙的方式存储可变长度数字。我很高兴我帮助:) – Kaslai 2012-03-01 05:38:48

+0

至于单个文件的东西,我将不得不依靠我的操作系统技能......如果我的块在磁盘上可变大小,由于外部碎片复制将是可怕的...也许是一个分页系统的索引在文件的开头?如果我不得不寻呼分页索引怎么办? * faints * – Philip 2012-03-01 05:40:48

3

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

您需要什么取决于您正在讨论的数据量以及您想要的平台特定性。你似乎在谈论一款2D游戏,所以该块不可能是大。常规的C或C++文件IO功能可能会足够好。最坏的情况下,您可能需要将它们粘贴到异步文件IO和处理的线程中。

真的,只要开始做明显的事情。如果它成为一个问题,请尝试使其与简单的线程构造异步。你可能不应该走的太远。

+0

嗯,好吧,不要数据库。 Ehhhh块的大小是可变的,但它们越大,其他事情就越快(难以解释)。他们目前是1024x1024(高达1 MB),但512x512和256x256绝对是选择。 – Philip 2012-03-01 04:57:20

+0

我会告诉你什么时候1mb是百日咳...... – fazo 2012-03-01 05:02:18

+0

@Philip:如果你正在谈论1MB大块,你真的不需要做太多特别的事情。只需加载它们并处理它们。再次,如果响应是一个问题,请使用线程。 – 2012-03-01 05:12:38

1

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

如果你有几千个文件小于4 kB页面,我会用数据库。如果文件大于该文件,则使用文件。数据库不会帮助您的吞吐量 - 只有您的延迟。

+0

谢谢,我没有考虑磁盘延迟。我可能会结束一个数据库,具体取决于。数据库可能会伤害我的吞吐量吗? – Philip 2012-03-01 05:05:41

+0

通过将这些松散的文件粘贴到TAR或Zip文件中,您可以获得相同的优势。 – 2012-03-01 05:12:04

+0

焦油或拉链的缺点是你必须阅读整个事情。他说他只想一次将部分数据读入内存。因此,我不会使用单个文件 - 操作系统必须加载整个文件并将其保存在磁盘缓存中。 – danimator 2012-03-01 05:20:22