結局、両方の方法から何かを使用しました。次のコード スニペットは、私が行った方法を説明するのに役立ちます。
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;
}
}
Multimap
最終的には guava を使用するよりも便利なデータ構造を見つけようとするでしょうが、現時点では機能しており、これらのクラスのパブリック API の残りの部分を具体化する作業に進むことに抵抗はありません。この回答が他の人に役立つ場合はArrayListMultimap
、この実装のパフォーマンスが厳密なテストを受けていないことに注意してください!