現在、自分で書かれたコンポーネントベースのエンティティエンジンの変種を使用して、ゲームをプログラミングしています。 私は私のエンティティと、彼らが持っているコンポーネントを定義するように、私が使用するようにシステムの残りのため適切にアドレスするために、次のアイデアを使用することを考え出し:コレクションからコレクションを取り出すときのオブジェクトのダウンキャスト
異なるコンポーネントを識別するために使用class Entity {
...
:
enum ComponentID() {
BODY,
GRAPHICS,
INVENTORY;
}
...
は、すべてのコンポーネントを保持する必要があります
EnumMap<ComponentID, ModelComponent> components = new EnumMap<>(ComponentID.class);
}
まず、我々は含まれるModelComponentとボディ、グラフィック、AIなど、いくつかの異なる具象サブクラスと呼ばれるスーパークラスを持っていますModelComponentを拡張します。
コンポーネントEnumMapは、エンティティが持つすべてのModelComponentsへの参照を保持する必要があります。 システムに特定のコンポーネントを尋ねるときに問題が発生します。私のゲーム内のどこかには、私がアクセスしたい場合は言うので、キャストが必要とされている
public Body getBody() {
return (Body) components.get(ComponentID.BODY);
}
:私は例えばボディコンポーネントを取得したい場合は物理学のクラスは、いくつかの衝突を計算したいので、私のようなコードを記述しますエンティティの速度は、私が呼び出すことになる:
Vector2 velocity = entity.getBody().getVelocity();
しかし、getVelocityは()のみコンクリートsublass本体内に定義されている方法です。
私の質問です:これは、サブクラスへのダウンキャストの適切な使用ですか?明らかにGraphicsコンポーネントはBodyコンポーネントとはまったく別のことをするため、両方とも完全に異なるメソッドを持つため、より良いデザインでダウンキャストを回避できるかどうかはわかりません。
EDIT:
1)もちろんプレイヤー、敵、トリガーなどのようなエンティティのより具体的なサブクラスがあります。私はこの質問に答えるために重要であるかもしれない以下の詳細を言及するのを忘れてしまった
それらはすべて異なるModelComponentsの組み合わせを持つ必要があります。 プレイヤーは敵と同じ場所にAIコンポーネントを必要としません。このリファクタリングと
2)私の目標は私のゲーム内でインスタンスのすべてのエンティティは、これらのフィールドのすべてを持っているでしょうので、フィールド
Body body;
Graphics graphics;
Inventory inventory;
Ai ai;
を取り除くことでした。短い答えは
public ModelComponent get(ComponentID id) {
return components.get(id);
}
3つの列挙定数しかありません。なぜ特定のタイプの3つのフィールドとして定義するだけではないのですか? –
Guavaの['ClassToInstanceMap'](https://github.com/google/guava/wiki/NewCollectionTypesExplained#classtoinstancemap)のようなものを考えてみてください。 – shmosel
@Jorn_Verneeそれは素晴らしい質問です。実際には、それは現在のコードのように見えます。私はこのリファクタを、より多くの異なるコンポーネントに対してより柔軟にコードを作成しようと試みました。 – edisontrent1337