2012-02-06 17 views
1

を汎用関数を使用して、私は三つの基本的なオブジェクト...全てから派生している私は、C#/ XNAで物理エンジンを作っていますC#/ XNAで衝突検出のための

スフィア キューブ 飛行機

を持っています

ゲームオブジェクト

私はゲームオブジェクトのリストにすべての私のオブジェクトを格納し、私はこのリストをループしたいとfoの正しい機能に行きますCheckCollision関数を呼び出すことができるだろうRオブジェクト

などの各ペアは

、外出先ではスフィア、

GO2ある球

if(CheckCollision(go, go2)) 
{ 
    //do stuff 
} 

bool CheckCollision(Sphere one, Sphere two) 
{ 
    //Check Sphere to Sphere 
} 

bool CheckCollision(Sphere sphere, Plane plane) 
{ 
    //Check Sphere to Plane 
} 

であり、私はそれだけで使用することwithour正しい機能に行きたいですチェックの場合。

ありがとうございます。

+0

[複数のディスパッチ通知アルゴリズムをC#で最適化する]の可能な複製(http://stackoverflow.com/questions/2367903/optimizing-multiple-dispatch-notification-algorithm-in-c) – phoog

+0

@Ramhound構文はどうでしたか無効?サンプル全体にファイルを含めることはできませんでした。なぜなら、ポイントを取得するために必要なのは、実行時にパラメータを決定しなければならない機能をオーバーロードしたいと思ったからです。 phoog:私の問題で仮想ディスパッチを検索することを知らなかった。リンクに私をリダイレクトするのではなく、答えてくれてありがとう。 – chrispytoast

+0

@chrispytoast - 忘れてしまいました...あなたのサンプルコードに何が間違っているかを説明する時間はありません。 –

答えて

4

あなたは、仮想ディスパッチを使用することができます。

abstract class GameObject 
{ 
    abstract bool CheckCollision (GameObject other); 
    abstract bool CheckCollision (Sphere other); 
    abstract bool CheckCollision (Cube other); 
    abstract bool CheckCollision (Plane other); 
} 

class Sphere : GameObject 
{ 
    override bool CheckCollision (GameObject other) { return other.CheckCollision(this); } 
    override bool CheckCollision (Sphere other) { /* ... implementation ... */ } 
    override bool CheckCollision (Cube other) { /* ... implementation ... */ } 
    override bool CheckCollision (Plane other) { /* ... implementation ... */ } 
} 

class Cube : GameObject 
{ 
    override bool CheckCollision (GameObject other) { return other.CheckCollision(this); } 
    override bool CheckCollision (Sphere other) { /* ... implementation ... */ } 
    override bool CheckCollision (Cube other) { /* ... implementation ... */ } 
    override bool CheckCollision (Plane other) { /* ... implementation ... */ } 
} 

class Plane : GameObject 
{ 
    override bool CheckCollision (GameObject other) { return other.CheckCollision(this); } 
    override bool CheckCollision (Sphere other) { /* ... implementation ... */ } 
    override bool CheckCollision (Cube other) { /* ... implementation ... */ } 
    override bool CheckCollision (Plane other) { /* ... implementation ... */ } 
} 

EDIT

は、あなたがこれを持っているときに何が起こるかを考えてみましょう:

GameObject go1 = new Sphere(); 
GameObject go2 = new Cube(); 
bool collision = go1.CheckCollision(go2); 
  • コールは抽象GameObject.CheckCollisionに行きます(GameObject)メソッドを球面上に配置します。
  • 仮想ディスパッチは、私たちが
  • Sphere.CheckCollision(ゲームオブジェクト)は、キューブの抽象GameObject.CheckCollision(スフィア)メソッドを呼び出しますSphere.CheckCollision(ゲームオブジェクト)に行くことを意味します。
  • 仮想ディスパッチは、私たちがCube.CheckCollision(スフィア)に行くことを意味します!

したがって、タイプチェックifのステートメントは必要ありません。

EDIT 2

https://stackoverflow.com/a/2367981/385844でエリックリペットの回答を参照してください。最初の選択肢 - 訪問者パターン - は基本的に上記のアプローチです。 https://stackoverflow.com/a/9069976/385844のエリックの他の答えもこの問題を論じています。

+0

メソッドのオーバーロードはコンパイル時に解決され、if-checksはまだ実行時に必要になることに注意してください。 –

+0

@ OlivierJacot-ゲームオブジェクトのオーバーロードの抽象的で反復的な実装を省略すると、チェックする必要がなくなります。私はロジックのウォークスルーを追加しました。 – phoog

+0

他のオブジェクトの 'CheckCollision'は常に' this'の静的型で呼び出されます。非常に賢い! (+1) –

1

私はあなたが一般的なアプローチを可能にするポリゴン、とあなたの形状を近似しない​​限り、これは、不可能であることを恐れています。あなたが正確な数学的表現で作業する場合は、異なるペアリングのための特別なソリューションが必要になります。あなたは異なる形状の型に番号を与える場合は(1、2、3)あなたは10* go.Number + go2.Numberとペアを表し、switch文でこの番号を使用することができます。また、あなたのアプローチはnオブジェクトの数はO(N^2)性能を有すること

注意。リストよりも適切なデータ構造の使用を検討してください。k次元空間にオブジェクトを格納するために、K-Dツリーがしばしば使用される。それらはしばしばグラフィックオブジェクトのバウンディングボックスと共に使用されます。各オブジェクトには、バウンディングボックスを生成するメソッドまたはプロパティがあります。 K-Dツリーは、必要な衝突チェックの回数を減らす。 Wikipediaのk-d treeを参照してください。

+0

+1のk-dツリー;それは私には新しいものです。 – phoog

+0

私はk-dツリーを調べます。私はまだ広範な段階を実装していませんが、幅広い段階で可能性のある衝突の多くを素早く取り除いて狭い段階で広い段階で正の結果を返すようにする予定です – chrispytoast

関連する問題