0

古典的なヘビゲームをプログラムしようとしています。私は論理が機能しています(食べる、成長する、動くなど)。今度は素敵なグラフィックを追加したいと思います。これまでのところ、このコードで作成したいくつかの醜いグラフィックがあります: (疑似コード)

void drawWorld(const std::vector<Tileable*> world_map) {
    for each Tileable {
         get position of Tileable
         get color of Tileable
         draw rectangle at position with color
    }
}

クラス Tileable は、Snakes マップ上のオブジェクトを表します -> リンゴ、壁、さらには蛇そのものです。オブジェクトの位置、ヘビがオブジェクトと衝突したときに何が起こるかなどを保存します -> ロジック。

しかし

りんごが長方形ではなく円だったらいいのに?

したがって、メソッド .draw() を持つクラス Drawable と、それぞれ独自の draw() メソッドを持つ派生クラス DrawableSnake、DrawableApple、DrawableWall、DrawableWhatever を追加したいと考えています。問題は、Tielable サブクラスをコレクション world_map から Drawable の適切なサブクラスに変換して、次のようにすることです。

void drawWorld(const std::vector<Tileable*> world_map) {
    for each Tileable {
         get drawable from tileable
         drawable.draw()
    }
}

RTTI で factory のようなものを使用することを考えています: (疑似コード)

Drawable convertToDrawable(Tileable* tileable){
     if tileable is Apple return DrawableApple
     if tileable is Wall return DrawableWall
     etc.
}

RTTI を使用せずに、これを行うより良い方法はありますか?

4

1 に答える 1

2

これは、ゲームエンジンの設計における一般的な問題です。これを解決する1つの方法は、エンティティコンポーネントベースのシステムに移行することです。

リンゴ、壁、ヘビはすべて同じクラスになります-「エンティティ」。各エンティティに、コンポーネントのリストを添付します。あなたの場合、「ComponentDrawable」はコンポーネントであり、「ComponentTileable」は別のコンポーネントである可能性があります。エンティティを作成するときは、その特定のエンティティを描画するために必要なデータを使用してComponentDrawableを初期化します。

エンティティから特定のタイプのコンポーネントを取得する方法が必要です。単純なシステムでは、各エンティティにコンポーネントポインタの配列を含めることができます。各コンポーネントタイプには、その配列に一意のインデックスがあります。配列内の空のスロットの値はNULLになります。

template<typename T> T* getComponent( Entity *entity ) {
    entity.component_array[T::index]
}

そして、変更した擬似コードの例は、次のようになります。

void drawWorld(const std::vector<Entity*> world_map) {
    for each entity in world_map {
         ComponentDrawable *drawable = getComponent<ComponentDrawable>( entity )
         if( drawable )
             drawable->draw()
    }
}

一部の人々は、機能をコンポーネントから除外し、それらをデータのキャリアとしてのみ使用することを好みます。そのルートを使用したい場合は、データ駆動型システムがComponentDrawableからのデータを使用して、各エンティティの正しい表現を描画できます。

于 2012-08-21T00:53:15.810 に答える