My question targets at the organisation or architecture of code for collision detection. Normally, your game has
different game entities, which have the ability to collide. For each game loop all of them (or using some advanced
techniques: a subset of them) have to check each other for a collision and react to that.
I see different possibilities to arrange that code, each of them with its pros and cons. Starting very simplistic
(please do not care about sophisticated performance issues), there could be a class just crossing every game
entity with others for the collision check.
Every game entity carries its own (generic) method for checking a collision and the proper reaction, e.g.
checkCollision(GameEntity other)
{
if(boundingBox.intersects(other.boundingBox))
{
reactToCollision(other);
}
}
- the entity knows about its collision method
- about how to react (change its own state)
Problem one:
When the collision method has a generic parameter, it lacks the ability to react to a certain type of collided
game entity. So I can check that a collision occurred, but not differ between a rocket collision or that of an
astroid… which can result in a different state.
You could make advantage of polymorphism and add a method for each other type:
checkCollision(Rocket other)
{
if(boundingBox.intersects(other.boundingBox))
{
takeDamage(other)
}
}
checkCollision(Astroid other)
{
if(boundingBox.intersects(other.boundingBox))
{
explode(other)
}
}
- can react to every derived game entity individually
- poor design, because every new entity needs an additional method -
Sure you can use instanceof to avoid multiple methods, but that smells as well
Problem two:
Who is responsible to apply the effects of the collision? Imagine a rocket hits a ship. The collision scheduler
(by chance) started to take the rocket and does something like:
rocket.checkCollision(ship);
We have these effects of that collision:
- the rocket is destroyed
- the ship’s health is reduced by the rocket’s damage
That could be handled:
- completely in the rocket’s method:
void collideWithShip(Ship ship)
{
ship.takeDamage(getDamage());
explode();
}
- for the case that the ship first was checked, the same:
void collideWithRocket(Rocket rocket)
{
takeDamage(rocket.getDamage());
rocket.explode();
}
- it could be split up, so that every entity only changes its own state:
Rocket:
void collideWithShip(Ship ship)
{
explode();
}
Ship:
void collideWithRocket(Rocket rocket)
{
takeDamage(rocket.getDamage());
}
The third version seems to be the cleanest one for me, because it does not require an game entity to know too much
about others and defines its own behaviour. On the other hand, what is more true: Does a ship actively take the damage information
from the rocket, or does the rocket apply damage to the ship?
Problem three:
When the collision effects are split up like in the last example, the collision scheduler has to do something like this:
void manageCollisions()
{
// iterate all entities, rockets ships …
…
if(rocket.checkCollision(ship))
{
ship.reactToCollision(rocket);
}
}
Meaning that both collision effect happen at the same time, so that e.g. state changes are visible to other game entities, which
are checked within the same cycle. But then the ship has to be marks as having already collided with this rocket entity. Otherwise
the scheduler would grab the ship to check for collision and redo it for the rocket.
I know that there a quite a lot of thoughts mixed up in this post and there are variants of putting this code out of the entities into
a manager class (which would have knowledge about the effects). But this is the very essential about these questions: How do you
approach this OO-issue and with what success/ drawback?