基于x / y坐标高效查找数组元素

时间:2013-06-01 16:35:03

标签: java

我写了一个java自上而下的2D游戏,它使用生成的图块作为地图。每个图块由包含其x / y坐标的Tile类描述。

当他们在地图上移动时,我需要能够让玩家“打开”。玩家类知道它当前的x / y,而Tile类知道它被分配给的x / y。

目前,需要渲染的所有切片都存储在Tile[][]中。我对java很新,但似乎不是一个好主意(如果可能的话)只是简单地使用我想要的数据索引的x / y坐标 - 主要是因为我目前渲染的瓷砖可能并不总是从0,0开始。假设玩家在1000,1000时加载了已保存的游戏 - 当我不需要时,我肯定不会从0,0加载游戏。

那么,存储这些坐标的最佳方法是什么?

在PHP中可以完成,因为我知道数组不关心从0开始的索引:

$tiles[1000][1000] = new Tile()

但我不确定Java推荐的方法是什么。不得不遍历每个单独的区块并检查x / y是否匹配,效率非常低。

3 个答案:

答案 0 :(得分:2)

老实说,你问的是一个非常高级的话题。这种涉及大型地图的项目实际上无法用简单的数组来完成。有些人会建议使用简单的偏移和动态数组,但效率极低。

但是,我可以给你一个建议。您可以以块的形式加载切片。比如说,每个块是一个32乘32的2D数组。您可以加载当前块和周围的块,而不是通常加载围绕播放器位置的图块。例如,假设位置1000,1000落在块C中。然后加载块C和所有周围的块。当您从块C移动到块D时,您卸载围绕C的块,而是加载围绕块D的块

块类看起来像这样:

class Chunk {
    private Tile tiles[32][32];
    private Coordinate origin; // (0, 0) on this chunk's array is actually equal to origin on the map
    // Example: if the chunk started at (128, 128), then origin would be (128,128)
    ...
    public static Chunk loadChunk(...) { ... }
    ...
}

你需要Map类来帮助定位和加载块:

class Map {
    public Chunk currentChunk;
    public ArrayList<Chunk> loadedChunks;
    ...
    public ArrayList<Chunk> getSurroundingChunks( Chunk ch ) {...}
    ...
}

几乎所有使用大型地图的游戏都会以大块地图的形式加载(我的游戏是一个值得注意的例子,尽管该游戏的编程通常很差)。

当然,它在算法上很复杂,你需要进一步研究它,而不仅仅是阅读这篇文章。但它应该为您提供一个适用于任何大小的地图的强大系统,并且已被证明可以在现实世界中使用。

该系统的一个缺点是,由于垃圾收集,在Java中很难预测卸载。但是,我不知道一个强大的加载系统,至少不会受到Java垃圾收集器的轻微伤害。

请注意

这种技术也称为延迟加载。这意味着您只需将实际需要的内容加载到内存中。这是用于加载大量可预测数据的最佳技术,因为它允许您最小化加载时间和内存消耗。基于块的加载并不是唯一的延迟加载,但我甚至可以说它可能是最好的。

答案 1 :(得分:0)

您可以使用Map来保存数据,并使用Coordiate对象作为关键字。 Coordinate对象应实现equalshashCode。这应该非常快速和简单。

您可以向地图添加项目:

map.put(new Coordinate(1000,1000), new Title(...));

你可以通过以下方式恢复它:

Title title = map.get(new Coordinate(1000,1000));

答案 2 :(得分:0)

另一种方法是使用Dictionary来存储切片。它不一定是最有效的,但它会起作用:

java.awt.Point p = new java.awt.Point(1000,1000);
Tile t = // however you get your tiles
java.util.Dictionary<java.awt.Point, Tiles> theDictionary = new java.util.Dictionary<>();
theDictionary.put(p, t);