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
\$\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\$
  • \$\begingroup\$ Can this be achieved in not functional language, for example in Java? \$\endgroup\$ – nikoliazekter May 5 '15 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 '15 at 19:28
  • \$\begingroup\$ So i have collisonCallbacks for half of my collidable objects? And how do i initialize these maps? \$\endgroup\$ – nikoliazekter May 6 '15 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 '15 at 13:48
  • \$\begingroup\$ I added more code to make this more clear. \$\endgroup\$ – mklingen May 6 '15 at 13:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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