2012-02-06 7 views
1

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

Сфера Куб Plane

что все происходит от

GameObject

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

например

идти является сферой,

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

Поэтому никаких проверок типа if не требуется.

EDIT 2

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

+0

Обратите внимание, что перегрузка метода разрешена во время компиляции и что при проверке по-прежнему потребуется время выполнения. –

+0

@ OlivierJacot-Descombes абстрактная и повторяющаяся реализация перегрузки GameObject должна устранять необходимость в проверке. Я добавил прохождение логики. – phoog

+0

Хорошо, я вижу, что 'CheckCollision' другого объекта всегда будет вызываться со статическим типом' this'. Очень умно! (+1) –

1

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

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

+0

+1 для дерева k-d; это ново для меня. – phoog

+0

Я рассмотрю дерево k-d. Я еще не реализовал свою широкую фазу, но я планирую, чтобы моя широкая фаза быстро устранила многие из возможных столкновений, так что моей узкой фазе придется иметь дело только с теми, которые положительно относятся к широкой фазе – chrispytoast