Типичное решение состоит в том, чтобы сделать два уровня отправки следующим образом:
class Thing
{
public abstract void Collide(Thing other);
public abstract void CollideWithSpaceship(Spaceship spaceship);
public abstract void CollideWithAsteroid(Asteroid asteroid);
};
class Spaceship : Thing
{
public override void Collide(Thing other) {
other.CollideWithSpaceship(this);
}
public abstract void CollideWithSpaceship(Spaceship spaceship)
{
// Handle Spaceship -> Spaceship collision...
}
public abstract void CollideWithAsteroid(Asteroid asteroid)
{
// Handle Spaceship -> Asteroid collision...
}
}
class Asteroid : Thing
{
public override void Collide(Thing other) {
other.CollideWithAsteroid(this);
}
public abstract void CollideWithSpaceship(Spaceship spaceship)
{
// Handle Asteroid -> Spaceship collision...
}
public abstract void CollideWithAsteroid(Asteroid asteroid)
{
// Handle Asteroid -> Asteroid collision...
}
}
Это становится немного громоздким, так как количество разных классов увеличивается, но у него есть кое-что для этого:
- Это быстро. Он опирается на встроенную динамическую диспетчеризацию языка, которая
довольно хорошо оптимизирован.
- Это безопасно. Вы заметите, что там нет кастинга.
Недостатком является:
- Не ограничено расширением. Добавление нового класса требует от вас прикосновения
все остальные.
Более расширяемое решение состоит в создании двумерной таблицы диспетчеризации, в которой каждая ячейка идентифицирует пару сталкивающихся классов. В каждой ячейке вы помещаете функцию, которая обрабатывает столкновение между этими двумя типами классов. Это тоже хорошо работает, но немного обманывает систему типов. Вы закончите кастингом, и вам придется найти хороший способ определить класс.
Я бы не использовал поддержку C # dynamic
. Я уверен, что это будет слишком медленно для физического движка.
Я также укажу, что существует стек разработки игр , который намного лучше отвечает на подобные вопросы. Увидимся там!