2

コンポーネント ベースのエンティティ システムを使用するゲームを作成しています。私が実装している最初の 2 つのコンポーネントは、EntityRepresentation と EntityState です。表現はアニメーションを保持し、状態はエンティティがゲーム イベントにどのように反応するかを決定します (EntityStates の例: 立っている、ジャンプしている、攻撃している、死んでいる、落下している)。

EntityRepresnetation は、エンティティの EntityState に応じて、画面に描画するアニメーションを決定します。エンティティが「ジャンプ」状態の場合、対応するアニメーションが再生されます。(EntityRepresentation::changeAnimation() 関数を参照してください。)

これが大まかなクラスの書き方です...

class EntityRepresentation
{
  public:
    void draw(float x, float y, long currentTime, DrawingContext& dc) {
        // ...
    }

    void changeAnimation(const EntityState::Id& stateId) {
        currentAnimation = animationMap_[stateId];
    }

  private:
    map<EntityState::Id, const Animation*> animationMap_;
    const Animation* currentAnimation_;
};

現在のアプローチで本当に気に入らないことがあります... >:( EntityState::Id 部分。現在、EntityRepresentation は、保持する各アニメーションを特定の EntityState::Id にマップします。ID はすべてのクラスに固有です。これは EntityState から派生します (インスタンスではなく、クラスに固有です). これらの ID は基本的に、クラスのコンストラクターで手動で記述しなければならない文字列です。ゲームをスクリプト可能にします (Python)。

ID に関するこの問題を軽減する方法について、アドバイスをいただけないでしょうか。ID も使用するコンポーネント ベースのシステムの実装をゲームでたくさん見てきましたが、それでも好きではありません。それは私を間違った方法でこするだけです。

カプセル化を維持しながら、EntityRepresentation が EntityState の型を知る必要がないように、設計変更を提案できるかもしれません。

4

3 に答える 3

1

各 EntityState に関連付けられた ID がコンパイル時に必要ないと仮定すると、私が使用した 1 つのトリックは、ポインターを ID として使用することです。これは、EntityState がシングルトンの場合に特にうまく機能します。この場合、シングルトン インスタンスのアドレスを ID として使用するだけで済みます。それ以外の場合は、ID ごとに小さなメモリ チャンクを静的に割り当てると問題なく動作します。

class EntityState {
public:
    EntityState(void *id) : mId(id) { }
private:
    void *mId;
};

class EntityStateJump : public EntityState {
public:
    EntityStateJump() : EntityState(getId()) { }
private:
    void *getId() {
        static void *id = new int;
        return id;
    }
};

編集:静的な初期化順序の問題を回避するための小さな変更。

于 2011-06-16T12:50:56.973 に答える
1

Stateパターンを使用して設計を実装することをお勧めします

class EntityState
{
public:
    EntityState(const Animation* animation);
    static const EntityState* getStandingState();
    static const EntityState* getJumpingState();
    static const EntityState* getAttackingState();

    const Animation& getAnimation() const;

protected:
    const Animation* pAnymation_;
};

class EntityRepresentation
{
public:
    void draw(float x, float y, long currentTime, DrawingContext& dc) {
        // ...
        const Animation& animation(state_->getAnimation());
    }

    void changeState(const EntityState* newState) {
        state_ = newState;
    }

private:
    const EntityState* state_;
};

void EventHandler(EntityRepresentation& entity)
{
    entity.changeState(EntityState::getJumpingState());
}
于 2011-06-16T13:13:40.077 に答える
1

typeid() を使用してください。それが目的です。const type_info*キータイプとしてa を使用できます。

または、仮想関数を呼び出して現在のアニメーションを取得するなど、実際の継承を使用することもできます。これははるかにスマートです。

于 2011-06-16T13:15:08.547 に答える