1
\$\begingroup\$

In my game, I have plenty of objects that can collide. Literally, most of them can collide with each other. The problem I'm facing is that I can't come up with some good collision detection. How can I resolve collisions for lots of objects in such way that I don't end up with class that has more than 1000 lines of code with enormous conditional constructs like this?

    if (firstBodyUserData == "rocket"
            && secondBodyUserData == "car_body") {
        resolveRocketAndCarBodyCollision(firstBody, secondBody, contactData);
    } else if (firstBodyUserData == "rocket"
            && secondBodyUserData == "gas_tank")
        resolveRocketAndGasTankCollision(firstBody, secondBody, contactData);
    //...many more dumb lines of code for every particular object in my game

And don't forget about all these "resolving methods" after if statements.

To make question more specific, I use Box2D with its ContactListener and Artemis-odb entity-component-system framework so I don't really have classes for my entities and that kind of exacerbates the problem but main question is in resolving bunch of different types of collisions.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

What you want to do is register collision callbacks for each kind of body.

// You have a map from bodies to functions of bodies.
Map<BodyData, Function<BodyData> > collisionCallbacks;
// Invoke the function associated with that kind of body.
collisionCallbacks[firstBodyUserData].Invoke(secondBodyUserData);

// An example collision function
void resolveRocketCollision(BodyData data)
{
     // This is also really horrible. You don't want to be checking conditions 
     // like this. Instead, you will want to indirect this one step further to
     // the *type* of the object, using virtual function calls.
     if(data == "car_body") ...
     else if(data == "gas_tank") ...

     // That is, it should look like this:
     if (data.HasProperty(Health))
          ...
     if (data.HasProperty(Explodes))
          ..
     ...
}

// Registering the function
collisionCallbacks["rocket"] = resolveRocketCollision;

Avoiding function pointers

In Java, you don't have function pointers, so it might be better to have an interface with a "resolvecollision" method like this:

public interface CollisionResolver
{
    void Resolve(BodyData bodyData, CollisionData collision);
}

Then your map would be something like this:

Map<BodyData, CollisionResolver> collisionCallbacks;

And you invoke it like this:

collisionCallbacks[firstBodyUserData].Resolve(secondBodyData, collisionData);

Avoiding a big static map

Obviously it's bad practice to carry around a big map of collision callbacks. You will have to use (drum roll) object oriented programming. Instead of storing strings as your user data, store the objects themselves. Then your function just becomes:

void ResolveCollision(BodyData body1, BodyData body2, CollisionData collisionData)
{
    body1.Resolve(body2, collisionData);
}

And, each of your bodies implements the CollisionResolver interface. For example, if you want a rocket to explode anything that has "health" you do this:

class Rocket implements CollisionResolver
{
   public void Resolve(BodyData otherBody, CollisionData collisionData)
   {
       if (otherBody.HasProperty(Health))
       {
           ExplodeRocket();
           otherBody.Die();
       }
   }
}
\$\endgroup\$
7
  • \$\begingroup\$ Can this be achieved in not functional language, for example in Java? \$\endgroup\$ May 5, 2015 at 17:49
  • \$\begingroup\$ Yes, using Java lambdas or anonymous internal classes. You can also just implement a function in your user data class that gets called directly. \$\endgroup\$
    – mklingen
    May 5, 2015 at 19:28
  • \$\begingroup\$ So i have collisonCallbacks for half of my collidable objects? And how do i initialize these maps? \$\endgroup\$ May 6, 2015 at 11:51
  • \$\begingroup\$ Yes, you have collision callbacks for every type of object that needs different behavior when colliding. If you're clever you can get this down to just 2 or 3 types. You register a callback whenever the object gets created. It'd be helpful to know why you need a big map of different collision resolutions. Usually you just attach a "sensor" object to your entity, then check collisions on that sensor for relevant types of objects. \$\endgroup\$
    – mklingen
    May 6, 2015 at 13:48
  • \$\begingroup\$ I added more code to make this more clear. \$\endgroup\$
    – mklingen
    May 6, 2015 at 13:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .