Collision handling (not detection)

Started by
13 comments, last by Ravuya 17 years, 11 months ago
@AsOne: I think you should google up on the double dispatch and visitor patterns. Most likely, there will also be an explanation there as to why enums and downcasts are not a good idea ;)

-Markus-
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Advertisement
Cygon:
I see, it seems you can avoid using downcasts and enums just by function overloading, and the trick of ...
Quote:
virtual void CollideWith(Asteroid& inAsteroid) {  inAsteroid.CollideWith(*this);}
Link

[Edited by - AsOne on June 7, 2006 12:55:54 PM]
If you mean you use the function signature to work out which collision mechanics to follow, that is far worse than a switch inside the function! Now when you add a new type of collision object, you have to write a new function in every class that is collidable with! ... instead of just adding a new case clause to those objects with which the new type of collision makes a difference.

I admit that sticking a switch in every classes Collide method is rather ugly. However a typical game would only have perhaps three types of collision object: static (i.e. walls and other things that stop everything else), physics-active (i.e. bodies that cause a 'proper' physics collision response, like players, moving balls, rockets maybe) and physics-inactive (i.e. things where there is no physics involved, just entity updates, like bullets, health packs and so on). So the Collide functions would only have three main branches.

You then need to think a bit more carefully than I did before about where damage goes. I guess something like
interface IDamagable { int Health { get; } void Damage(int amount, GameObject source);}

... which players, monsters, destroyable wall entities etc derive from. Then a bullet would, in its collision method, do
if(other is IDamagable) (other as IDamagable).Damage(howMuchDamage, this);


Edit: just read your link on double dispatch, and ewww!
Yeah, I still don't see why using enums or dynamic_cast is so bad in this situation, it seems like way more work to write the function prototypes for all the collisions and then implement all the functions themselves then to just use a switch.

e.g. if using the double dispatch method the entity interface would need all types of collisions defined as pure virtual. However, what if some game entity like a gas cloud or something does nothing to itself when collided with anything (except for if it hits the player, it vanishes). You would end up with all of the collision functions (except one) for the gas cloud as just empty functions, gross.

Post before mine says it better ...
Quote:Original post by Bob Janova
If you mean you use the function signature to work out which collision mechanics to follow, that is far worse than a switch inside the function! Now when you add a new type of collision object, you have to write a new function in every class that is collidable with! ... instead of just adding a new case clause to those objects with which the new type of collision makes a difference.


I agree, just using a swtich would make this neater IMO.
void GasCloud::OnCollision(IEntity *other){  switch (other->getEntityType())  {    case ENTITY_PLAYER:      delete this;  }}// ...void Player::OnCollision(IEntity *other){  switch (other->getEntityType())  {    case ENTITY_GAS_CLOUD:      health--;      break;    // ...  }} 


Can someone tell my why using enums or dynamic_casts is so bad in this situation? Specifically to the OP's question, why would doing this be bad in a collision response system?
I have all objects that inherit from PhysicalObject implement an OnCollision method with a force value, and a pointer to another PhysicalObject (which might expose public traits like IsOnFire or whatever).

Then in my game loop, when I detect the collision, I make both involved objects call OnCollision with the other one and let them work it out internally with their response (a RubberBall object might set its velocity based on the force, or explode, and a Statue object won't move but might crumble if the force is significant enough or the colliding object is explosive). It's pretty simple (thank you polymorphism) but effective. Then after I've run the OnCollision I just check the destroyed status of both objects and discard those that have gone onto the great bit bucket in the sky.

Depending on what properties your base PhysicalObject class exposes, you can have a wealth of different object types. I'm not sure if this is "good" OO but it seems to work for me.

This topic is closed to new replies.

Advertisement