Communicating between entities colliding

Heya! I’m making a 2D platformer and I already have the collision working well. Sadly, there isn’t enough communication between objects that are colliding with each other that will allow anything specific to happen when a collision occurs. Lemme describe what currently happens.

I have two interfaces. The Collider interface enforces collisions on game entitites implementing the Moveable interface. Entities implementing the Moveable interface store information regarding its velocities and previous positions so that a Collider may do it’s job.

When a Collider enforces a collision on a Moveable, the Collider does whatever it needs to do to enforce its collision (positioning the Moveable and setting its velocities to whatever), then it invokes one of the following methods that the Moveable interface specifies: hitLeft(), hitRight(), hitTop(), hitBottom(). So far, this merely alerts a Moveable that a particular side has been hit. It’s useful when I want an animation to play when a side has been hit, but it doesn’t provide enough information.

Currently, when my Player entity (which implements Moveable) is touching the ground, if |velocityX| > 0, then the running animation starts. What if the platform that the Player is on is moving, though? The Player’s vx will be greater than 0, so the animation for running will play even though the Player SHOULD be standing still on the moving platform. I want to go about fixing this by allowing there to be a bit more communication between the Collider and the Player when a collision occurs, but I don’t want to bloat the Moveable and the Collider interfaces too much.

My first thought was to have the methods hitLeft(), hitRight(), etc… Require a multitude of parameters such as…

public void hitLeft(float relativeVx)
{
// Codeity code…
}

The parameter ‘relativeVx’ would be a velocity x that the Player’s run animation would be centered around (instead of having the animation depend on Player’s vx being greater than 0).

BUT WAIT! THERE’S MORE!

What if after I’ve finally refactored my code, I decide that I also want sound to be attached to collisions? Now I need to add more parameters to the enforceCollision method, then refactor my code once more!

Then I though of something… What if I sent in an object representing the collision that happens? It would allow me to add a multitude of arguments and store it in one object like so:

public void hitLeft(CollisionEvent e)
{
// Montage of code…
}

Huh, reminds me of swing…

Each time that I invoke this method, of course, I will be reusing the CollisionEvent object instead of creating a new one. This will work because the CollisionEvent object will be muteable. The Moveable taking in the CollisionEvent from the Collider will be able to pick and choose which elements of the event to consider, and which to ignore. The Event could have variables pointing to sounds, the Collider enforcing the collision, visual effects that may be generated because of the collision (sparks, dust particles), info about the Collider’s trajectory, etc… Since I’m not instantiating a new CollisionEvent object each time this happens, I don’t have to feel bad about making the garbage collector discard a bunch of short-lived objects, because I’m not.

My only regret is that, one way or another, there is a little bit of bloat that comes about from this process. The CollisionEvent object may not need a sound attached to it, or the relativeVx variable could be useless because the Collider never moves.

I’m not quite sure if this is the best way to handle this situation, so I’d like to hear what other people have to say!

I do use recycled collision objects as well.
The event/listener concept is very simple but powerful for organizing code.
You could attach multiple listeners responsible for different tasks like:

  • low level physics handling
  • maintaining the environment, like spawning enemies, opening doors
  • effects, animation, sounds
  • trigger the game ai
  • attach the network module in a multiplayer game

A collision object should only describe what has happened but not how to handle it, so it should not store concrete sound names, e.g.

Good to see that I’m not insane. So, does this imply that I could shamelessly write something like this?

public void hitLeft(CollisionEvent ce, SoundEvent se)
{
// Insert competent programmer’s code here!
}

This WOULD solve my problem in the specific scenario that I’ve put forth, but I don’t want it to hurt me later on.

The hit methods are there primarily to represent a course of action that should take place in a Moveable object that has been hit. In reality, it merely alerts it and sends a bit of information regarding the hit. The Collider is still responsible for positioning the Moveable in the event of a collision. Sending an event object would simply let the object getting hit handle the rest of the collision in a polymorphic way (usually, this this triggers an Animation in the Entity). Anywho, I’m worried that passing sound in a method that is supposed to represent collision will end up being a tad arbitrary. I’ve had bad experiences in writing god classes, so that’s why I’m mentioning this.

What say you?

I would rather start off with something like this:

public void onCollision(CollisionEvent ce) {
   ...
}

You have events and event handlers. One handler could look up an appropriate sound according to the collision participants and play it.
Clearly assign responsibilities and do not mix them.
It could make sense to create different kind of collision events, like player-opponent or player-platform.

I think I get what you’re saying. Forgive me, as I have never written an event driven environment of my own. Let me paraphrase, if you’ll let me.

Would this make my interface, Moveable (the entity that moves and can have collisions enforced on it) the handler, and my interface Collider (the entity that enforces collisions on Moveables) the entity that sends an event object representing the characteristics of the collision? The Moveable getting hit would handle the event based on the data within it, and the Collider would be the sender.

Instead of having four methods (hitLeft, hitRight, hitUp, hitDown), I could have one called hit(CollisionEvent e)
and e might contain data about which side was hit, what type Collider was responsible for the collision, the time it occurred, the type of surface the Collider has (eg: Gravelly, icy), the relative velocities that should be adopted by the Moveable, etc).

That would be the obvious start. It could make sense though to have dedicated handlers. For example, to prevent from duplicate collision handling when two entities collide, let a third party handle them both.

Just do what is most convenient. If you always have to branch inside the hit method according to the collision type, add more methods and call the right one directly.