2009-12-09 9 views
7

QTでゲームを構築しています。 GraphicsScene上のすべてのオブジェクトは、GraphicsPixmapItem(Player、Obstacles、bombs ...)から継承されます。私は衝突の影響を与えたいと思います。例えば、プレイヤーがホバーしてボーナスを得ると、彼はそれを選ぶことができます。 QTフレームワークでは、コリジョンアイテムを取得できますが、instanceof関数がないため、どのタイプであるのかわかりません。任意のヒント ?ゲームでコリジョンエフェクトを実装する方法は?

編集:私は衝突を取得 "イベント"私がしたいことは、さまざまな衝突を処理することです。私はより良い言葉で別のquestionを作った。

答えて

9

設計上の考慮事項:

私は彼らのグラフィック表現からゲームオブジェクトを継承するお勧めすることはできません。どうして? 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(); } 
+0

+1優れた論文。写真はそれをより良くするでしょう。 ;-) –

+0

あなたの説明に感謝します。 C++がゲーム開発者にとって良い選択ではないことは本当ですか? – amirouche

+2

C++は、ゲーム開発者のIMOのための最良の選択の1つです。必要に応じてメモリや低レベルコールへのアクセスをより詳細に制御できます。しかし、私はC++やjava以外のゲームを作ろうとは決してしなかったので、私は偏っています。 –

4

1は、アイデア:
継承:それぞれに衝突することができますプレイヤーは、オブジェクトが例えば擬似コードのような

C++を必要とするものは何でもないCollideWithPlayerメソッドを持つオブジェクト

class Item : GameObject { 
public: 
    CollideWithPlayer(Player p); 
} 

class PointBag : Item { 
public: 
    CollideWithPlayer(Player p) { p.points += 5000; } 
} 
1

ますNvidia PhysXやBulletのような外部ライブラリを使用して、衝突が発生したときにコールバックを設定することができます。 Qtのコリジョンシステムを使用しないライブラリを使用することで、物理フレームワークをシミュレートした後、GraphicsPixmapItemのプロパティを更新して、物理シミュレーション内の状態を反映させることができます。

0

次のQtの例をご覧ください。衝突するマウスの例

これはかなり簡単で、Qtを使った基本的な衝突の扱いについてはかなり良い紹介です。

迅速にまとめ、各オブジェクトは、あなたが、その後のアイテムがお互いに触れたりしていないかどうかを知るためにこれらの境界ボックスを使用します...あなたはそれが使用するスペースを与えるバウンディングボックスを持っています...

お役に立てれば !

+1

http://doc.trolltech.com/4.6/graphicsview-collidingmice.html –

+0

http://web.archive.org/web /20100409105849/http://doc.trolltech.com/4.6/graphicsview-collidingmice.html – Fuhrmanator

関連する問題