0

私のゲームでは、通常、基本クラスの「エンティティ」から派生したすべての NPC / アイテムなどがあります。次に、それらは基本的に「update」と呼ばれる仮想メソッドを持ち、フレームごとにゲーム内の各エンティティに対してクラス化します。これはデメリットが多いパターンだと思います。ゲーム全体でさまざまな「ゲーム オブジェクト」を管理するには、他にどのような方法がありますか? これには他のよく知られたパターンがありますか? 私は基本的に、巨大な継承ツリーと仮想関数にまたがる基本クラスからすべてを派生させるよりも優れたモデルを見つけようとしています。

4

2 に答える 2

2

代わりに動作の継承を含む別のパターンがあります。

例: 剣 (ファンタジー スタイルのゲーム) は、 を継承しDescribableて、プレイヤーに説明できるようにすることができます。またDoDamage、ダメージを渡す処理を継承します。からさらに継承するGrabableため、プレイヤーはそれを「つかむ」ことができます。

鎧の一部は、プレイヤーがそれを着用できるようにするDamageReductionだけでなく、与えられたダメージを減らすために継承することができます.Wearable

大きくて深い継承ツリーの代わりに、小さくて浅い継承ツリーがたくさんできます。もちろん、欠点は、多くのクラスを作成し、発生する可能性のあるさまざまな動作やイベントについて考えなければならないことです。

于 2012-11-02T20:44:25.480 に答える
1

オブジェクトが将来の特定の時点で更新を要求するようにします。

struct UpdateToken {
  UpdateToken() {}
  /* ... */
};
class Updater {
  // ...
  struct UpdateEntry
  {
    UpdateToken token;
    Time when;
    bool repeats;
    Time frequency
    std::function<void()> callback;
  };
  // Various indexes into a collection of UpdateEntries
  // sorted by when and by token so you can look up both ways quickly
public:
  UpdateToken RegisterUpdate( Time t, std::function<void()> callback ); // once after time t
  UpdateToken RegularUpdate( Time t, std::function<void()> callback ); // every time t

  void UnregisterUpdate( UpdateToken );
};
Updater* GetUpdater();

// use:
class Foo
{
  UpdateToken token;

  void DoUpdate()
  {
    std::cout << "I did it!\n";
  }

  void PlanRepeatingUpdate( Time t )
  {
    if (!GetUpdater())
      return;
    if (token.valid())
      GetUpdater()->UnregisterUpdate(token);
    token = GetUpdater()->RegularUpdate( t, [&]()->void
    {
      this->DoUpdate();
    });
  }
  ~Foo() { if (token.valid() && GetUpdater()) GetUpdater()->UnregisterUpdate(token); }
};

ここには、将来のイベントのソース (Updater()) と、1 回の繰り返しまたは一連の繰り返しのコールバックを登録できる j ランダム クラス Foo があります。

0.1 秒、1 秒、または 1 時間で更新を要求できます。たまたま破壊された場合、または更新が不要な場合は、登録を解除することができます。

次のイベントをすばやく呼び出して、トークンによって更新を検出できるように、Updater にいくらかの労力を注ぐ必要があります。Boost の二重インデックス コンテナーを見たことがあります。または、プライマリ std::set (または順序付けられていないセット) と、一意の順序付けを持つ最初のセットへのイテレーターのセカンダリ セットを使用して、手動で処理することもできます。慎重に (イテレータが無効になる原因に注意を払い、イテレータのセットに無効なものが含まれていないことを確認する必要があります)。

上記は、グローバルな Updater() インスタンスも効果的に使用していますが、これは通常理想的ではありません。

于 2012-11-02T21:27:01.777 に答える