3

artemis-odblibGDXを使用して、ターン ベースのタイル マップ ベースのゲームに取り組んできました。

草、砂、水、山など、マップにさまざまな地形タイプが必要でした。これらのさまざまな地形タイプごとに、通過する移動コストが異なり、ゲーム プレイに関連するさまざまな追加プロパティがありました。

現在、いくつかの異なるアプローチを検討しています。

  1. マップをシステムGameMapSystemにして、各タイプの地形に関連するコンポーネント ( TerrainStats、場合によってはスペル エフェクト コンポーネントExplodingなど) を持つエンティティによって表される各タイプの地形を持つことができます。私の主な関心事は、地形タイプのエンティティへのタイルのマッピングを管理する方法です。int[][]概念的には、地形エンティティの ID に対応する値でを維持するのと同じくらい簡単なはずですが、その場合、一時的なマーカー コンポーネント ( Exploding) が特定の地形タイプすべてに一度にアタッチされます。これは最適とは言えません。それでは、タイルごとに個別のエンティティが必要になるのでしょうか? その場合、エンティティ フレームワークに追加のオーバーヘッドを作成していませんか?

  2. また、ゲーム マップと地形タイプを POJOS にして、特殊効果用のマーカー コンポーネントを使用してマーカー エンティティを作成することも検討しました。ただし、このようにGameMapすると、さまざまなシステムがオブジェクトを処理できるようにするために、オブジェクトを勝手に渡しているように見えます(レンダリング、衝突、パスなど)。さらに、ゲーム マップは、パス ロジックを実行するために、その時点でマップ上にあるエンティティをその位置で追跡する必要もありませんか? 可能であれば、エンティティ フレームワークのドメインの下でエンティティの管理を完全に維持することをお勧めします。メンテナンスが少し簡単になるからです。

まだ調べていないアプローチがあるかどうか興味があります。それ以外の場合は、見落としていた方法 1 を修正する方法がない限り、方法 2 に傾倒しています。

4

2 に答える 2

1

結局、両方の方法から何かを使用しました。次のコード スニペットは、私が行った方法を説明するのに役立ちます。

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、この実装のパフォーマンスが厳密なテストを受けていないことに注意してください!

于 2014-04-23T00:13:31.987 に答える