C#/ XNAでの衝突検出に汎用関数を使用する

私はC#/ XNAで物理エンジンを作っています、私は3つの基本的なオブジェクトを持っています...

球体 キューブ 飛行機

これらはすべてから派生したものです

ゲームオブジェクト

I store all my objects in a list of ゲームオブジェクトs and I would like to loop through this list and be able to call a CheckCollision function that will go to the correct function for each pair of objects

例えば

goは球です、

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
}

私はそれがチェックの場合に使用しなければならない正しい関数に行くことを望みます。

ありがとうございました。

1
追加された 著者 phoog,
@chrispytoast - それを忘れて...あなたのサンプルコードに何が間違っているかを説明する時間がない。
追加された 著者 Security Hound,
@Ramhoundどのように構文が無効でしたか?サンプル全体にファイルを含めることはできませんでした。なぜなら、ポイントを取得するために必要なのは、実行時にパラメータを決定しなければならない機能をオーバーロードしたいと思ったからです。 phoog:私は自分の問題のために仮想ディスパッチを探すことを知らなかった。リンクに私をリダイレクトするのではなく、答えてくれてありがとう。
追加された 著者 chrispytoast,
@Ramhound - もしあなたが私のコードを打ち破り、それを無効にすることができれば、改善できると思う方法を教えてください。私はあなたがどこに欠陥を見つけているのか分かりません。あなたがそれを私に指摘してもらえれば、私は試して改善することができます。
追加された 著者 chrispytoast,

2 答え

あなたは仮想ディスパッチを使うことができます:

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 ... */ }
}

編集

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

GameObject go1 = new Sphere();
GameObject go2 = new Cube();
bool collision = go1.CheckCollision(go2);
  • 呼び出しは、球上の抽象的なGameObject.CheckCollision(GameObject)メソッドに移動します。
  • 仮想ディスパッチとは、Sphere.CheckCollision(GameObject)に行くことを意味します。
  • Sphere.CheckCollision(GameObject)は、キューブ上で抽象的なGameObject.CheckCollision(Sphere)メソッドを呼び出します。
  • 仮想ディスパッチとは、Cube.CheckCollision(球)に行くことを意味します!

したがって、 if 文の型チェックは必要ありません。

2を編集

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

4
追加された
@ OlivierJacot- GameObjectのオーバーロードの抽象的で反復的な実装を解除すると、チェックする必要がなくなります。私はロジックのウォークスルーを追加しました。
追加された 著者 phoog,
@ OlivierJacot-Descombesは正確です。私は最近、エリック・リッペルトの作品を見たことを思い出しました。そこでは、ダブル・バーチャル・ディスパッチについて議論しました。私はそれを完全には読まなかったが、今私はそれを再び見つけようとしている。
追加された 著者 phoog,
リンクを見つけました(重複した質問への回答): stackoverflow.com/a/2367981/385844
追加された 著者 phoog,
メソッドのオーバーロードはコンパイル時に解決され、if-checksはまだ実行時に必要になることに注意してください。
追加された 著者 Olivier Jacot-Descombes,
他のオブジェクトの CheckCollision は、常に this の静的型で呼び出されます。非常に賢い! (+1)
追加された 著者 Olivier Jacot-Descombes,
ありがとうたくさんのphoog。私はこの質問の答えを探していたが、うまくいくものを見つけることができなかった。私はちょうどこれを実装し、それは素晴らしい動作します!再度、感謝します。
追加された 著者 chrispytoast,

あなたが一般的なアプローチを可能にするポリゴンで形状を近似しない​​限り、これは不可能であると私は恐れる。あなたが正確な数学的表現で作業する場合は、異なるペアリングのための特別なソリューションが必要になります。異なる形状タイプ(1,2,3)に数値を与える場合、 10 * go.Number + go2.Number でペアを表現し、このステートメントをswitchステートメントで使用できます。

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

1
追加された
k-d木に対して+1;それは私には新しいものです。
追加された 著者 phoog,
私はk-d木を調べます。私はまだ広範な段階を実装していませんが、幅広い段階で可能性のある衝突の多くを素早く取り除いて狭い段階で広い段階で正の結果を返すようにする予定です
追加された 著者 chrispytoast,