我最终使用了两种方法中的一些东西。以下代码片段应该有助于说明我采用的方法:
class TerrainType {
public String displayName;
public String regionName;
public int movementCost;
/* additional properties omitted */
/* constructors omitted */
}
此结构包含有关地形类型的相关信息,包括移动成本和其他与游戏相关的统计数据(为简单起见,我省略了其余部分)、地形类型的显示名称(如果已检查)以及TextureRegion
要从中提取的名称TextureAtlas
我的渲染器对我如此友好。
class GameMapSystem extends EntityProcessingSystem {
@Mapper private ComponentMapper<MapPosition> pm;
@Mapper private ComponentMapper<SolidObject> som;
private ListMultimap<MapPosition, Entity> entityByLocation;
private int[][] map;
private int width, height;
private Array<TerrainType> terrainTypes;
/**
* Accepts an Array of TerrainType objects and an 2d integer array with
* values corresponding to indices into the array for the correct type.
*
* In my case, these values are gleaned by reading a level description
* file, but any source should be fine.
*/
public GameMapSystem(Array<TerrainType> terrainTypes, int[][] map) {
super(Aspect.getForAll(MapPosition.class));
this.terrainTypes = terrainTypes;
this.map = map;
this.width = map.length;
this.height = map[0].length;
this.entityByLocation = ArrayListMultimap.create();
}
public boolean isOccupied(int x, int y) {
List<Entity> entities = entityByLocation(new MapPosition(x, y));
for(Entity e : entities) {
if(som.has(e)) {
return true;
}
}
return false;
}
@Override
protected void inserted(Entity e) {
this.entityByLocation.put(pm.get(e), e);
}
@Override
protected void removed(Entity e) {
this.entityByLocation.remove(pm.get(e), e);
}
/* additional EntityProcessingSystem overrides omitted */
}
然后它EntityProcessingSystem
以被动模式连接到我的世界。不应该有任何真正的理由在这个系统中对我的世界进行任何处理,我真正想要的是能够收听inserted
并将removed
实体放入地图中的事件。在这种情况下,经理会矫枉过正,因为它会告诉我每个实体都被插入或删除,而我只关心与地图相关的实体(或者更具体地说是与地图相关的具有位置的实体)。然后,我有一些单独的寻路逻辑,它使用额外的(此处未显示)方法来引导 AI,只需从世界对象请求这个被动系统即可。
为了完整起见,MapPosition
该类也如下所示。重要的是包含equals()
并hashcode()
帮助将其MapPosition
用作集合中的键。
public class MapPosition extends Component
{
public int x, y;
public MapPosition(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object other) {
if(!(other instanceof MapPosition)) {
return false;
}
MapPosition pos = (MapPosition)other;
return (pos.x == this.x && pos.y == this.y);
}
@Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + this.x;
hash = 59 * hash + this.y;
return hash;
}
}
我最终可能会尝试找到比使用 guava 更方便的数据结构Multimap
,但它现在可以工作,我很乐意继续充实这些类的其余公共 API。如果此答案确实对其他人有所帮助,请记住,ArrayListMultimap
此实现的性能尚未经过严格的测试!