0

ここからゲーム状態マネージャー(イントロ、メインメニュー、ゲームプレイなど)を使用します。ただし、1つの問題があります。非常にミニマルな例:

class cApp //manages the states and gives them access to window
{
public:
cApp (RenderWindow & ref) : window(ref) {}
void changeState(cState *);     //these function realy doesn't matter
void update();
void draw();

RenderWindow & window; //the same as in the article, this class not only manages state but gives them access to window etc

private:
std::vector <cState *> states;
}

状態:

class cState
{
public:
cState(cApp * ptr) : app(ptr) {}
virtual void update() = 0;
virtual void draw() = 0;
protected:
cApp * app;
}

これまでのところすべてが良いです。問題は、これが基本的なフレームワークの一部であるということです。したがって、cAppは非常に基本的なものであり、ウィンドウへのアクセスのみを提供します。ただし、ユーザーがゲームでネットワークを使用したい場合があります。ネットワークエンジンは単一の状態の一部ではないため、よりグローバルな(つまり、cApp)レベルである必要があります。

したがって、ユーザーは次のことを行います。

class cNetworkedApp : public cApp
{
public:
cNetworkedApp(RenderWindow & ref1, NetworkEngine & ref2)
: networking(ref2), cApp(ref1)
NetworkEngine & networking; //initialized in cNetworkedApp constructor
}

class CharacterCreationState : public cState
{
 CharacterCreationState(cApp * ptr) : cState(ptr) {}
 //implement pure virtual functions
 void draw()
 {}
 void update()
  {
      //THE PROBLEM
      //the state needs to access the network engine so casting is required
      cNetworkedApp * ptr = static_cast<cNetworkedApp*>(app))
      ptr->networking.sendSomething();
  }
}

唯一の明白な解決策は、cAppで可能なすべてのものを含めることですが、これはフレームワークです。もちろん、物理エンジンやサウンドエンジンなどの一部のエンジンは、問題がないように状態に設定するものですが、ネットワークシステムなどは、すべての状態で使用できる1つのオブジェクトである必要があります。そして、すべてのアプリがそれを使用しているわけではありません。

このコードを再設計する必要がありますか、それとも大丈夫ですか?

4

1 に答える 1

1

ポリモーフcAppィックタイプの名前付きリストを保持することができます。Engineつまりmap<string,Engine*>、ユーザーcAppは、特定のエンジンがあるかどうかを尋ねることができます。

NetworkEngine純粋な抽象のサブクラスになりますEngine

アップデート

与えられた特殊な型であると確信しているポインターを扱うときは、ポインターを使用static_castすべき型にキャストできるかどうかを照会するときに、を使用する必要がありますdynamic_cast

私自身、最初のケースに対してより安全なアプローチをとっています。アサーションを使用して、型をキャストできることを保証し、static_cast通常のコードで使用します。

Engine* fetchedEngine = cApp.fetch("network");
assert( dynamic_cast<NetworkEngine*>(fetchedEngine) != NULL );
NetworkEngine* network = static_cast<NetWorkEngine*>(fetchedEngine);

タイプのオブジェクトのみをNetworkEngine「ネットワーク」名に付ける必要がありますが、誰かが誤って他の何かを付けた可能assert性があります。これにより、オーバーヘッドを気にすることなく、より安全になります。

于 2013-02-14T14:27:14.313 に答える