Java中游戏实体位置的有效映射

时间:2010-06-12 04:53:53

标签: java algorithm data-structures dictionary

在Java(Swing)中,我说我有一个2D游戏,我在屏幕上有各种类型的实体,例如玩家,坏人,通电等。当玩家在屏幕上移动时,按顺序为了有效地检查玩家附近的内容,我认为我希望根据他们的位置对角色附近的东西进行索引访问。

例如,如果玩家'P'在以下示例中步入元素'E'...

| | | | | |
| | | |P| |
| | |E| | |
| | | | | |

...会做类似的事情:

if(player.getPosition().x == entity.getPosition().x && 
              entity.getPosition.y == thing.getPosition().y)
{
    //do something
}

这很好,但这意味着实体保持其位置,因此,如果我在屏幕上有多个实体,我将不得不循环遍历所有可用的实体并检查每个位置与玩家位置。这似乎真的很低效,特别是如果你开始获得大量的实体。

所以,我怀疑我想要某种类似

的地图
Map<Point, Entity> map = new HashMap<Point, Entity>();

并将我的点信息存储在那里,以便我可以在固定的时间内访问这些实体。该方法的唯一问题是,如果我想将实体移动到屏幕上的不同点,我将不得不搜索HashMap的值以寻找我想要移动的实体(因为我不知道它的效率低效)提前点位置),然后一旦我发现它从HashMap中删除它,并用新的位置信息重新插入它。

我应该在这里使用哪种数据结构/存储格式的建议或建议,以便根据实体的位置有效访问实体,以及基于实体的职位?

3 个答案:

答案 0 :(得分:4)

空间划分可能有效。

你可以做固定的划分,比如统一网格,或加权网格,除非你的地图上有热点,事情变得异常聚集。对于每个占用的分区,创建一个包含其所包含的所有实体的容器。

插入是恒定时间。删除是 n (您的实体总数)的实际上无穷小部分,假设 n 非常大并且您已经有效地设置了分区。邻近查找与移除共享相同的运行时。尽管如此,技术上仍然是O( n )。如果分区变得异常拥挤,这将变得明显。

要获取实体的 x 单位内的所有实体的列表,您必须首先获得以2 x 宽方形正方形为中心的所有分区的列表你的实体。如果您使用网格分区,这是相当简单的。接下来,循环遍历这些分区中的所有实体,并将每个实体返回距离 x 或更少的实体。

更复杂的分区方法是动态分区树中的空间,确保没有分区可以包含多于给定数量的实体。如果分区变满,则将其沿空间均值划分,并创建两个空间分区,使每个分区保留原始分区实体的一半。这使得插入和查找具有对数运行时,因为您无法再在恒定时间内发现所需的分区,但是在给定上限分区的情况下,删除变为恒定时间。

答案 1 :(得分:3)

如果EntityPoint之间存在一对一的映射,并且您希望能够在两个方向上进行映射,那么bimap是最自然的数据结构。

Guava有BiMap<K,V>实现,支持BiMap<V,K> inverse()视图操作。这只是一种观点,所以它的成本并不高。

或者,您可以管理自己的Map<Entity,Point>Map<Point,Entity>,但这会重新发挥作用。

答案 2 :(得分:0)

效率低,因为我不提前知道它的Point位置
我是否正确,该实体对象中没有位置信息?我建议添加它。或者,您可以拥有当前实体位置Map<EntityIdType, Point>的地图并首先获取位置。没什么好看的。