The typical solution is to do two levels of dispatch like this:
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...
}
}
It gets a bit cumbersome as the number of different classes goes up, but it has some things going for it:
- It's fast. It relies on the language's built in dynamic dispatch which is
pretty well optimized.
- It's typesafe. You'll note there's no casting going on.
The downside is:
- It isn't open-ended to extension. Adding a new class requires you to touch
all of the others.
A more extensible solution is to build a 2D dispatch table where each cell indentifies a pair of colliding classes. In each cell, you put a function that handles collision between those two class types. That works well too, but it cheats the type system a bit. You'll end up doing some casting and you'll have to come up with a good way to identify a class.
I would not use C#'s dynamic
support. My strong hunch is that it will be too slow for a physics engine.
I'll also point out that there's a Game Development Stack Exchange that's much better at answering questions like this. See you there!