存储和加载2D无限过程生成的基于图块的世界

时间:2018-07-25 13:27:06

标签: memory optimization lua corona procedural-generation

背景

我正在研究2D无限世界。它是基于图块的,这意味着我的地形完全由正方形组成。您可以想象它像2D Minecraft(从上方看地形)。

我实施了标准的块系统,将地形切成8x8的小方块区域,随着玩家在世界各地移动,地形区域会被加载和删除。到目前为止,它工作起来非常流畅,没有任何打or或滞后。我正在使用Lua和Corona SDK。

问题:

由于玩家可以修改地形,因此我需要一种快速高效的系统,以便在玩家加载新块时将其保存在内存中,并且需要一种从内存中加载这些块的系统它们以前已经加载过。

这是发生问题的地方。它需要经常读取和保存到文件(内存),这会导致明显的延迟。不能将块变大。

我尝试过的解决方案,但是都引起了滞后:

a)首先,我实现的一个明显的解决方案是为每个块创建一个文本文件,并以图块名称作为字符串。它看起来像这样:x12y10.txt,在文件内,我只是转储了所有切片名称,以便将它们放置在屏幕上:"Grass Grass Water Sand Sand Sand Grass Grass..."。那行得通,但是加载字符串很慢,所以我尝试了另一种解决方案:将图块另存为索引。

b)将图块保存为索引。我将每个磁贴与一个数字配对。由于数字越短,它们占用的内存就越少,加载速度也越快。我给每个图块指定了自己的索引:Grass -> id 1Water -> id 2Sand -> id 3,依此类推。这样,我只需要保存1或2个字符,而不是每个图块保存完整的字符串。我的txt文件现在看起来像这样:"1 1 2 3 3 3 1 1..."。这种方法效果更好,但仍会导致滞后。

c)我所做的下一个改进是内存中块的组织方式。我没有将所有块都转储到一个文件夹中,而是为每个x坐标创建了一个文件夹,并将所有具有x值的块放在其中。

所以代替这个:

  • 所有块的文件夹:x0y0.txtx0y1.txtx0y2.txtx1y0.txtx1y1.txtx1y2.txt

里面有所有块的文件夹,我有这个:

  • 文件夹x0:x0y0.txtx0y1.txtx0y2.txt

  • 文件夹x1:x1y0.txtx1y1.txtx1y2.txt

我不确定这对于少量的块有多大帮助,但是我很确定对于数千个块有改善。

可能的解决方案?

我有一些改进的想法,但我想听听您对解决方案的看法。

a)将地形保存为二进制文件吗?

b)我已经阅读了有关Minecraft区域格式的信息,确实试图理解其工作原理,但是由于了解甚少,所以没有得到。因此,如果有人知道并且可以向我解释他们的系统,我将非常感激。

c)另一种更快的文件格式?

d)是否会使许多文件夹访问缓慢?有更好的选择吗?

2 个答案:

答案 0 :(得分:2)

我真的觉得这是cs-101的问题,但无法立即用谷歌搜索出任何答案,因此请快速总结一下。

所有文件只是字节序列。如果我们正在谈论读写原始字节,那么没有一种格式会使64个字节出现在内存中的速度比另一个字节快。

文本文件是一个字节序列,其值略有限制(限制是,如果您希望标准文本程序显示它)。文本文件中的字符串"11"(位序列:110001110001)的加载速度不会比“二进制”文件中的不可打印位100000100000的加载速度快。

构造目录至少可以减少尝试尝试打开的文件时系统检查的节点数量。但是文件系统的基础机制非常复杂,并受许多因素影响。总体猜测是,即使是小的文件也要频繁读取会很慢。而且所有文件都带有一些存储开销(系统信息以保持跟踪和排序),小文件的有用/辅助信息比率较低。我知道至少有一个带有可变地图的2d项目,在几年前将hdd移到更大的文件之前,它们就变得嘶哑而咕and。

您不必使块变大,这是不同的,但是您可以将它们写入同一文件。 您可以拥有一个兆字节的文件,而不是一个64字节的百万个文件(假设每个块使用一个字节)。玩家可以修改或四处走动一百万块。如果将数据解压缩到表中,它将占用更多空间,但是不必解密所有字符串,只需解密当前所需的字节即可。是的,在lua中修改兆字节字符串将导致创建另一个兆字节字符串,这很慢,但是您不必每次都这样做,也可以将字符串拆分为较小的字符串并进行修改。而且只有在需要时才写。 I / O缓冲甚至可以在没有您干预的情况下发生,但通常对于大文件也很有用。 是的,每个图块会有一个字节以上的信息(每个图块有2 ^ 8个可能的状态很多),系统保持不变。

对于纹理来说,done也是一样,因为在单个大勺中的单个大块中加载数据比在各处搜索一小部分要快。索引单个较长的内存区域也比追逐指针快。

最重要的是,您可能尝试读取/写入的字节数少于内存中的字节数。例如,通过压缩数据。

答案 1 :(得分:2)

在Minecraft中,除非进行了访问/修改,否则不存储块,否则将生成它们。

这将为您提供一个系统,其中仅需要存储玩家已修改的块,并且每次都使用相同的随机种子重新生成未修改的区域。

创建修改层次结构...块是8x8块,创建一个8x8块的超级块,并且如果8x8超级块中的任何一个已被修改,则仅查找文件。

可能将所有超级块存储在一个文件中,这将限制文件的数量(添加更多文件的确会降低系统的速度,并且还低效地使用了系统上的空间)。

如果您有任何空闲时空,则可以在播放器附近缓存块,并预加载将要访问的修改区域。这样可以限制所需的可见滞后时间