設計上の考慮事項:
私は彼らのグラフィック表現からゲームオブジェクトを継承するお勧めすることはできません。どうして? 1つのゲームオブジェクトの複数のグラフィック表現(ゲームビューの場合やミニマップの場合など)を複数表示することができます。この関係は、「プレーヤー」は「グラフィック表現」であり、「プレーヤー」は「グラフィック表現」ではない。よりよい解決策は、継承ではなく合成を使用することです。他の素晴らしい効果は、あなたがQtによって提供されているものに満足していない場合、他の衝突検出のカプセル化が可能です。デカップリング、...真実も、単純なゲームの場合は十分です。
単純なゲームロジックでは、他のオブジェクトがアクティブオブジェクトに反応する継承。複雑なゲームの仕組みにはあまりにも単純すぎるでしょう。
class Asteroid {
public:
virtual void CollideWithPlayer(Player&) { p.loseHealth(100); }
};
class ExplodingAsteroid: Asteroid {
public:
virtual void CollideWithPlayer(Player&) { explode(); p.loseHealth(1000); }
};
相互作用は複雑で(自分で動作し、多くのアクティブなオブジェクト)を取得した場合、あなたのオブジェクトを識別するために必要がある場合があります。
ありますがRTTIですが、ERMは、それが参照をお勧めするのは難しい:How expensive is RTTI? で短い:高価で、維持するのが難しい。
ダブルディスパッチを使用できます。 2つの仮想呼び出しを使用してオブジェクトを識別します。 問題:かなりの構文ですが、管理しにくい場合があります(特に新しいオブジェクトを追加する場合)、所有権の問題(詳細はこちら)。ウィキペディアから ゲームの例:
class SpaceShip {};
class GiantSpaceShip : public SpaceShip {};
class Asteroid {
public:
virtual void CollideWith(SpaceShip&) {
cout << "Asteroid hit a SpaceShip" << endl;
}
virtual void CollideWith(GiantSpaceShip&) {
cout << "Asteroid hit a GiantSpaceShip" << endl;
}
};
class ExplodingAsteroid : public Asteroid {
public:
virtual void CollideWith(SpaceShip&) {
cout << "ExplodingAsteroid hit a SpaceShip" << endl;
}
virtual void CollideWith(GiantSpaceShip&) {
cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl;
}
};
仮想機能ID
class GameObject() {
virtual getId() { return GAME_OBJECT; }
};
class Asteroid() {
virtual getId() { return ASTEROID; }
};
またはメンバー
class GameObject() {
ID getId() { return id; }
protected:
GameObject(ID id):id(id) {}
private:
ID id;
};
やIDの自動初期化とテンプレートを使用したとして(少し気が遠くなる構文、のはそれを省略してみましょう:O)
ゲームのループは次のようになります:
for each object
update by (fixed) time step
detect collisions and resolve them
あなたは発生します:
所有権の問題:小惑星に見舞われていると小惑星が、その後破棄されたとき
プレイヤーは健康を失う。..
Asteorid::collideWithPlayer(Player& p) { p.loseHealth(100); this->explode(); }
は今も
Player::collideWithAsteroid(Asteroid& a) { this->loseHealth(100); a.explode(); }
を考えます結果:コードの重複または不明瞭なゲームの仕組み
貧乏人のソリューション:あなたを助けるために他の誰かを呼び出す:O)
Asteorid::collideWithPlayer(Player& p) { resolveCollision(p, *this); }
Player::collideWithAsteroid(Asteroid& a) { resolveCollision(*this, a); }
resolveCollision(Player, Asteroid) { p.loseHealth(100); a.explode(); }
+1優れた論文。写真はそれをより良くするでしょう。 ;-) –
あなたの説明に感謝します。 C++がゲーム開発者にとって良い選択ではないことは本当ですか? – amirouche
C++は、ゲーム開発者のIMOのための最良の選択の1つです。必要に応じてメモリや低レベルコールへのアクセスをより詳細に制御できます。しかし、私はC++やjava以外のゲームを作ろうとは決してしなかったので、私は偏っています。 –