Использование общих функций для обнаружения столкновений в C # / XNA - PullRequest
1 голос
/ 06 февраля 2012

Я делаю физический движок в c # / XNA, у меня есть три основных объекта ...

Сфера куб Самолет

все они получены из

GameObject

Я храню все свои объекты в списке GameObjects, и я хотел бы пройтись по этому списку и иметь возможность вызывать функцию CheckCollision, которая перейдет к правильной функции для каждой пары объектов

например

Сфера - это Сфера,

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
}

и я бы хотел просто перейти к правильной функции без использования проверок if.

Спасибо.

Ответы [ 2 ]

4 голосов
/ 06 февраля 2012

Вы можете использовать виртуальную рассылку:

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)
  • Sphere.CheckCollision (GameObject) вызывает абстрактный метод GameObject.CheckCollision (Sphere) для куба.
  • Виртуальная отправка означает, что мы идем в Cube.CheckCollision (Sphere)!

Следовательно, операторы проверки типа if не нужны.

РЕДАКТИРОВАТЬ 2

См. Ответ Эрика Липперта по адресу https://stackoverflow.com/a/2367981/385844;. Первый вариант - шаблон посетителей - по сути является подходом, описанным выше. Другой ответ Эрика в https://stackoverflow.com/a/9069976/385844 также обсуждает эту проблему.

1 голос
/ 06 февраля 2012

Боюсь, что это невозможно, если вы не приблизите свои фигуры с помощью полигонов, что позволит использовать общий подход. Если вы работаете с точными математическими представлениями, то вам понадобятся специальные решения для разных пар. Если вы дадите числа различным типам фигур (1, 2, 3), вы можете представить пару с 10* go.Number + go2.Number и использовать это число в операторе switch.

Обратите внимание, что ваш подход имеет производительность O (n ^ 2), где n - это количество объектов. Попробуйте использовать более подходящую структуру данных, чем список. K-D-деревья часто используются для хранения объектов в k-мерном пространстве. Они часто используются в сочетании с ограничивающими рамками графических объектов. Каждый объект будет иметь метод или свойство, дающее ограничивающий прямоугольник. K-D-деревья позволили бы сократить количество необходимых проверок столкновений. См. k-d tree в Википедии.

...