Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

In a 2D game where you have a lot of possible combination of collision between objects, such as:

object A vs object B => object B vs A;

object A vs object C => object C vs A;

object A vs object D => object D vs A;

and so on ...

Do we need to create callback methods for all single type of collision? and do we need to create the same method twice? Like, say a bullet hits a wall, now I need a method to penetrate the wall for the wall, and a method to destroy the bullet for the bullet!!

At the same time, a bullet can hit many objects in the game, and hence, more different callback methods!!!

Is there a design pattern for that?

share|improve this question
    
This answer explaining virtual dispatch on SO is very enlightening. –  Olivier Jacot-Descombes Oct 10 '12 at 22:14
add comment

3 Answers

You do not need to have a different collision callback method for each type of collision.

You could implement one callback: collisionEvent(objA, objB);

To treat different types of objects you can have collide-able objects implement an Interface ICollide that has a function, collideWith(obj); and perhaps getMass(); and possibly getSurfaceType(); Then each object checks the attributes of the object it collided with and responds appropriately. For instance a bullet may pass through a wooden wall, bounce off a metal sheet and knock off a tin can.

The insides of collisionEvent(objA, objB); will look like:

{
    objA.collideWith(objB);
    objB.collideWith(objA); // You may need to elaborate depending on the game
}

Instead of having a switch statement, you could use 'low resolution attributes' to keep things simple.

For instance add a density to each collideable object. It could be a Enum to reflect the needs of the game.

  1. Lets take a solid metal sheet, it will have a density of High and a bullet will check against that and bounce off it.
  2. A wooden wall will have a density of Low and the bullet will pass through.
  3. A thick sturdy plaster wall will have a Medium density and the bullet will get trapped inside it.

In reality I am pretty sure the bullet would pass through a plaster wall, that was just an example for a third option.

You will probably need a mass property if you have many objects of different sizes.

For instance, a tin can will be low density and have a low mass value, meaning it will bounce off when hit by a bullet and the bullet will continue in its trajectory. Some items will need to be of a fragile variety such as glass, so you will destroy the item if it is hit by a bullet and animate this process.

All the properties I described exist in physics engine except fragility, however physic engines mostly assume objects cannot pass through one another. You could try and override that behavior programatically. Simply by not checking/acting on collisions between bullets and materials of low density.

share|improve this answer
    
So inside that collideWith(obj) you still have to do maybe a switch statement for each kind of obj, right? Like switch(obj) case tinCan: //do whatever –  Ahmed Fakhry Oct 10 '12 at 6:32
    
I would agree with that. not sure I would be so specific.. I will elaborate. –  Arthur Wulf White Oct 10 '12 at 6:36
    
yes because that switch statement will be very ugly specially if that object collides with many others!! how would you do it then? –  Ahmed Fakhry Oct 10 '12 at 6:40
    
You should add basic properties to collide-able objects that reflect the way they behave during collisions. See my edit –  Arthur Wulf White Oct 10 '12 at 6:41
add comment

I recommend defining an interface for all of these object types (ICollidable, for example), that contains the following method:

void ApplyCollision(List<ICollidable> colliders)

In your collision detection loop, when examining obj_A for collisions, you create a new List<ICollidable>, and add all other objects to this, which collide with obj_A.

Once this list is built (you finished examining obj_A), you can call the ApplyCollision method with the list as an argument. In the ApplyCollision method, you're stepping through the items of the list, and yes: you will probably need a switch statement at this point, since a Bullet will probably be destroyed with a nice visual effect when it hits a Wall, while the Wall might only get a decal. And the Bullet will cause damage to a Player or a Vehicle, etc. But everything else is generic in the collision detection method.

share|improve this answer
1  
But wouldn't that be inefficient to rebuild that list of colliders every frame? Especially that I would have to do this for every object in the scene? –  Ahmed Fakhry Oct 10 '12 at 6:44
2  
@AhmedFakhry Well, nobody says you must do collision detection every frame - but that'd be a pretty safe bet. And your collision detection must have some kind of optimization, so that you don't actually do the precise detection for every object in the scene. As for the list... well, this is what collision detection is about: finding colliding objects. –  Marton Oct 10 '12 at 6:47
add comment

I had the following problem few months ago (I was implementing a little physics engine in C++), and I didn't get to any clean solution to this problem.

I try to share a little bit of what I came up with.

Do we need to create callback methods for all single type of collision?

Basically the answer is YES.

and do we need to create the same method twice?

Basically the answer is yes. You can eventually avoid creating the same collision dispatch method, but you would always need some double/triple dispatch technique in order to manage all possible collision combinations.


There would be a nice solution using Visitor pattern if C#(or C++ in my case) would allow multiple dispatch. I posted a quite generic question, but you can interpret the answer linked above like if:

  • Visitor->collision dispatcher interface (to be implemented)
  • Base-> Collidable interface (eventually exposing some common methods like GetMass(),...)
  • Derived1 -> Wall, Derived2-> Bullet (using your example)

You can emulate multiple dispatch in C# like shown here (You can eventually translate it from C++ to C#, but I don't think it's a good solution). This esoteric solution has several drawbacks:

  • bad performances: too much method calls. This is particularly negative because you usually need to handle a lot of collisions at almost each frame.
  • readability: even if visitor is a well know pattern, the multiple dispatch variant exposed in the link is not easy to understand
  • maintenability: even if all derived class share the same identical implementation, you can't enclose this inside a Macro, like would be possible in C++. So you'd have to modify all base classes implementations once you add a shape.

Finally I decided to use std::map with an std::pair as key, and a function pointer as value. You can achieve the same result in C# this way:

  • Define a common Collidable Interface
  • Implement a collision handler function for all collision pairs
  • Use a class or a struct to hold pair of collision object that also implements IEqualityInterface( let's call it ColliderPair)
  • Declare a dictionary to store delegates associated with each CollidePair:

     Dictionary<CollidePair, Action<Collidable,Collidable>> handlerTable;
    
  • Populate handlerTable with the desired delegates, for each combination of pairs, while initializing your app

  • When you need to resolve a collision, build a CollidePair and use it to find the right delegate into the Dictionary.

Sorry for the long esoteric answer :). I hope to have given you some hints. I post a C# implementation when I have time.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.