1

私は現在、ある種のゲームボード用の2Dベクトル配列をどのように作成すればよいかを考えています。

サイズは変化する可能性があるため、ボードはベクトルである必要があり、各「正方形」には、その正方形内にあるオブジェクトに関する情報が含まれている必要があります。

問題は、重複するオブジェクトが存在する可能性があり、オブジェクトが同じタイプまたはクラスではない可能性があることです。

これは私が現在検討していることです:(擬似コード)

struct Square {
    vector<enum type>;
    vector<pointers to objects>;
};

vector< vector <Square> >;

そして、ポインタは、それぞれが特定のオブジェクトを保持している異なるベクトル配列を指します。

そのような機能をどのように作成するか、あるいはこれが可能かどうかはわかりません。これは必要以上に複雑になる可能性があると真剣に考えています。

一部のオブジェクトはクラスである必要がありますが、1つのマスタークラスから継承するゲームボードクラスのすべてのタイプのオブジェクトを作成できます。しかし、最終的にはオブジェクトが完全に異なるため、それが大きな違いになるかどうかはわかりません。 。

私はただ盲目で、私がやろうとしていることを行うためのより簡単な方法を見逃していますか?配列内で重複する可能性のあるさまざまなタイプの要素を保持する2D配列ですか?

ヘルプ、スニペット、洞察をいただければ幸いです。

注:ボードのサイズは、作成後にチャンスがありません。オブジェクトはボード内を移動できる必要があります。

4

1 に答える 1

1

これが私が提案することです。

#include <boost/shared_ptr.hpp>

class GameObject {
  public:
    virtual ~GameObject() {}

    enum Type {
       FOO,
       BAR
    };
    virtual Type type() const = 0;

    virtual std::string name() const = 0;
    virtual void damaged() {}
};

class FooObject : public GameObject {
  public:
     Type type() const { return FOO; }

     std::string name() const { return "Foo object"; }
     void damaged() {
        std::cout << "Foo was damaged!" << std::endl;
     }
};

class BarObject : public GameObject {
  public:
     Type type() const { return BAR; }

     std::string name() const { return "Bar object"; }
     // Bar object doesn't respond to damage: no need to override damaged()
};

class Square {
   std::vector<boost::shared_ptr<GameObject> > objects;
};

class Board {
   // Details of the implementation here not important, but there
   // should be a class to hide them.

   Square* squares;
   int width, height;

   Board(int width, int height) :
     squares ( new Square[ width * height ] ),
     width ( width ),
     height ( height )
   {
   }

   ~Board() {
      delete [] squares;
    }

   Square& square(int x, int y) {
      if( x < 0 || x >= width || y < 0 || y >= height ) {
          throw std::logic_error( "accessed square out of bounds" );
      }
      return squares[ x + width * y ];
   }
};

概要:

  • ゲームボードに配置できるあらゆる種類のオブジェクトに対して単一の基本クラスを用意します。
  • このタイプのクラスには、たとえ些細なことであっても、仮想デストラクタが必要です。これは、GameObjectポインタを介して物事を削除するためです。
  • ゲームオブジェクトを区別する必要がある場合は、「type」値を返す仮想メソッドを使用します。
  • 使用する必要がない限り、その型の値は使用せず、代わりに意味のあることを行う他の仮想メソッドを使用してください。タイプ値を使用する(そして一般的にサブタイプにキャストする)ことは、最後の手段と見なす必要があります。たとえば(ゲームの詳細を自由に発明する):
    • すべてのオブジェクトには、カーソルをオブジェクトの上に置いたときに表示される名前があります。これはname()で返されます。
    • ゲーム内のイベントにより、オブジェクトが「損傷」する可能性があります。これは特定の種類のオブジェクトにのみ適用されるため、damage()に対するデフォルトのアクションは何もしません。ダメージに反応するFoo-objectsは、これを実際のアクションでオーバーライドします。
  • ただし、ボードを実装する場合は、正確な実装をクラスに隠してください。(これにvector <>を使用すべきではないことを示すものとして私のコードを受け取らないでください。これは間違いなく問題ありません。ここでは、vector <vector <>>に対して少し個人的な好みがありますが、それほど悪くはありません。)
  • ゲームオブジェクトには共有ポインタを使用します。
    • Boostには、広く使用されている優れた実装があります。
    • 共有ポインターを使用できない場合は、Squareクラス外のゲームオブジェクトの存続期間を制御し(たとえば、Boardクラスのすべてのゲームオブジェクトのマスターリストで)、Squareクラスで生のポインターを使用します。
    • 共有ポインタを使用するのが初めての場合は、最初にそれらを簡単に読んでください。それらは魔法ではありません。循環参照などの特定のことに注意する必要があります。
  • 必要に応じて、GameObjectに、そのGameObjectへのポインターを含む正方形または正方形の座標への「バックリンク」が必要になる場合があります。これにより、ボードからオブジェクトを簡単に削除して移動できます。
于 2013-03-24T09:22:27.313 に答える