5

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

当玩家在地图上移动时,我需要能够获得玩家“打开”的图块。player 类知道它当前的 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 是否匹配,这感觉效率非常低。

4

3 回答 3

2

老实说,你问的是一个相当高级的话题。这种涉及这么大地图的项目,真的不能用一个简单的数组来完成。有些人会建议使用简单的偏移量和动态数组,但这非常低效。

不过我可以给你一个建议。您可以分块加载图块。例如,每个块都是 32 x 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 的垃圾收集器的轻微伤害。

笔记

这种技术也称为延迟加载。这意味着您只将真正需要的内容加载到内存中。这是加载大量可预测数据的最佳技术,因为它可以让您最大限度地减少加载时间和内存消耗。基于块的加载并不是唯一一种延迟加载,但我什至可以说它可能是最好的一种。

于 2013-06-01T16:45:54.427 回答
0

另一种选择是使用字典来存储图块。它不一定是最有效的,但它会起作用:

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);
于 2013-06-01T16:44:52.530 回答
0

您可以使用 aMap来保存数据,并将对象作为键Coordiate。该Coordinate对象应实现equalsand hashCode。这应该工作得非常快速和简单。

您将项目添加到地图:

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

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

Title title = map.get(new Coordinate(1000,1000));
于 2013-06-01T16:41:01.480 回答