5

我正在制作一个基于 2D 瓷砖的游戏。我使用一个 2D 锯齿状数组来存储一个整数,然后渲染器根据该整数是什么来绘制某个图像。我的这部分代码可以正常工作,但是我已经到了不确定下一步如何进行的地步。

随着玩家继续游戏,我需要能够存储有关 2D 数组中每个单元格的信息,例如光照级别,或者用户单击该单元格的次数,或者图像的旋转值在该单元格中,或该图像的 alpha 级别等。

我能想到的唯一方法是为我使用的每条信息创建一个二维数组,就像我之前所做的那样。例如:

AlphaLevel[][]
NumberOfTimesClicked[][]

然后如果我需要(例如)检查用户点击单元格的次数 5,5 我可以做 NumberOfTimesClicked[5][5] 或者如果我需要设置旋转我可以做 SetRotation[5][ 5] = 90。

我不确定这是多么有效,为每条信息设置一个数组似乎并不具有内存效率。

这个想法是我有一个好的解决方案,还是有一个我没有想到的更好的方法?

任何建议都会很棒!谢谢

4

3 回答 3

22

制作一个Tile包含信息的对象,例如AlphaLeveland NumberOfTimesClicked,并制作一个锯齿状数组。然后,您只需要一个锯齿状数组来保存您的所有信息,而且它组织得更好,因为您可以轻松找到 aTile具有的所有属性。

如果您对内存优化感兴趣,NPSF3000 说结构会稍微好一点是正确的。在使用它们之前,请确保您熟悉值和引用类型的不同之处。

以较小的格式存储数据总是比不存储数据要大。除了尽可能地压缩当前数据外,还要考虑将不需要的旧数据存储到磁盘的方法,或者丢弃以后可以通过程序生成的数据。

最后一点:您确定需要压缩它吗?当我过去在 2D 瓦片系统上工作时,我发现我实际上存储了一些额外的数据以便提高速度,因为我实际上并没有使用那么多内存。运行一些数字以确保您实际上使用了足够的内存来进行值得优化。

于 2013-08-19T17:12:11.917 回答
5

我不确定这是多么有效,为每条信息设置一个数组似乎并不具有内存效率。

简短回答:您可以使用 Structs 作为替代方案 - 它可以通过简单地“将所有内容存储在一起”来摆脱额外的数组。


长答案:

数组的表示形式如下: Header:Data 其中标头是 4 字节的 Int32。

目前,您的存储可能如下所示:

IIII:B:B:B  //Byte array (e.g. alpha level)
IIII:SS:SS:SS  //Short array (e.g. num times clicked)
IIII:B:B:B  //Byte array

其中 I、B 和 S 分别代表 Int、Byte 和 Short 的一个字节。使用 Struct,您可以将它们全部存储在一起 - 如下所示:

IIII:BSSB:BSSB:BSSB

如果您使用类而不是它看起来非常不同,因为类存储在数组中作为对数据位置的引用:

IIII:RRRR:RRRR:RRRR
BSSB  //These can be stored anywhere in memory
BSSB  //These can be stored anywhere in memory
BSSB  //These can be stored anywhere in memory

因此,虽然结构可以节省一些内存,但并不是很多。使用类实际上会消耗你的记忆!但是,它使用的内存不必是连续的,这在存储大量大数据组(例如总计 1GB+)时会有所帮助,尤其是。在 32 位机器上……不过那是另一天的讨论。

当然,这纯粹是在讨论内存大小效率,如果您的工作负载在逐个字段的基础上进行计算,那么单个数组将更加缓存友好 - 因此效率更高。相反,如果您倾向于逐块地进行计算,那么反之亦然。类对于原始存储效率低下,但如果它们适合您的编码范式,可能会使开发更加容易。此外,当许多对象需要引用相同的数据时,类是很好的——它甚至可以通过减少重复来节省内存!

希望这会有所帮助,因为您可以看到对基础知识的良好理解会有所帮助。然而,最重要的是珍惜您的时间,以及是否/何时性能成为您自己的问题测试和基准!

免责声明:早上写的,可能有错误/有遗漏等。

于 2013-08-19T17:41:53.140 回答
0

四种方法是:

  • 为每个地图单元所拥有的每个属性定义一个锯齿状数组
  • 将多个单元格属性组合成一个结构类型(公开公共字段而不是属性以获得最佳性能和语义),并定义一个锯齿状数组
  • 定义一个不可变的类类型,该类类型包含多个单元属性,定义这些属性的交错数组,并使用默认实例初始化所有元素。
  • 定义一个包含多个单元属性的可变类类型,定义一个交错数组,初始化数组的每个元素以引用一个不同的对象实例,并且永远不会再次写入数组(仅仅改变它保存引用的实例) .

如果某些属性组可能会被靠近访问而其他属性不会被访问,则可以通过使用第二种方法来实现最佳性能,将经常在一起的事物分组。如果某些属性值的组合比其他属性值出现得更频繁,那么将这些特定属性组合到一个不可变类中可能是有意义的。不过,一般来说,对于内部数据类型,我的偏好是使用暴露字段结构类型的锯齿状数组。

对于这个应用程序,结构应该是不可变的口头禅是完全错误的。可变结构的语义不同于类;任何不理解的人可能会感到困惑。然而,这并不意味着应该避免使用结构。相反,这意味着任何想成为优秀程序员的人都应该了解结构的工作原理。所有暴露场结构的行为方式都相同,学习所有这些结构的行为方式不应该比学习如何使用典型的框架类花费更长的时间。

于 2013-08-19T23:41:12.947 回答