0

游戏是基于瓷砖的,但瓷砖实际上仅用于地形和寻路目的。Sprite 的移动是自由形式的(即,玩家可以穿过瓷砖的一半)。

这个游戏中的地图非常大。正常缩放时,图块为 32*32 像素,地图大小可以达到 2000x2000 或更大(400 万图块!)。目前,地图是瓦片数组,瓦片对象如下所示:

public class Tile {

    public byte groundType;
    public byte featureType;
    public ArrayList<Sprite> entities;

    public Tile () {
        groundType = -1;
        featureType = -1;
        entities = null;
    }
}    

其中groundType 是纹理,featureType 是占据整个图块(如树,或大石头)的地图对象。这些类型的功能非常常见,因此我选择将它们设为自己的变量,而不是将它们存储在实体中,实体是图块上的对象列表(项目、生物等)。出于性能原因,实体被保存到磁贴中。

我遇到的问题是,如果实体未初始化为 null,Java 就会用完堆空间。但是在我看来,将其设置为 null 并且仅在某些东西移入磁贴时才进行初始化似乎是一个糟糕的解决方案。如果一个生物在其他空的瓷砖上移动,则需要不断地初始化列表并将其设置回 null。这不是糟糕的内存管理吗?什么是更好的解决方案?

4

1 回答 1

2
  • 拥有一个包含所有精灵的单一结构(以 ArrayList 开头)。
  • 如果您正在运行一个游戏循环并在 sprite 列表中循环,例如,每隔 30-50 秒一次,并且最多有 200 个 sprite,那么这种结构本身不应该对性能造成影响。
  • 稍后,为了其他目的,例如碰撞检测,您可能需要修改单个 ArrayList 的结构。我建议从简单的、点头的解决方案开始整理你的游戏逻辑,然后根据需要进行优化。
  • 对于您的图块,如果空间是一个问题,那么与其拥有一个特殊的“图块”对象,不如考虑将每个图块的信息打包成一个字节、短或整数,如果实际上每个图块不需要太多特定信息的话。请记住,您创建的每个 Java 对象都有一些开销(为了论证,假设每个对象大约 24-32 个字节,具体取决于 VM 和 32 位还是 64 位处理器)。400 万字节的数组“仅”4MB,400 万整数“仅”16MB。
  • 如果每个图块需要 16 个字节的数据,则另一个图块数据的解决方案是,如果将图块的规范打包到单个基元中不切实际,则声明一个大的 ByteBuffer,每个图块的数据存储在索引(例如)tileNo * 16 处。
  • 您可以考虑不将所有图块实际存储在内存中。这是否合适将取决于您的游戏。如果每个单独的图块不需要太多数据,我会说 2000x2000 仍然在您可以明智地将整个数据保存在内存中的范围内。

如果您认为最后几点打败了面向对象语言的全部要点,那么是的,您是对的。因此,您需要权衡在什么时候选择“极端”解决方案来节省堆空间,或者您是否可以“摆脱”使用更多内存以获得更好的编程范例。每个图块有一个对象可能会使用(比如说)几百兆字节的数量。在某些环境中,这将是荒谬的。在其他几个千兆字节可用的情况下,这可能是完全合理的。

于 2012-12-03T18:05:01.213 回答