# Playing a sound on collision?

I'm making a pool game. I've separated the gameplay logic and the physics into two systems, entities and physics. Each entity holds a reference to a body which the physics system uses. The body itself holds a reference back to it's owner. When an entity collides with another entity, the Collided(Entity other) method is called on both.

What I'm trying to do now is to play a sound when both entities colliding are of a certain subclass. I'm not sure how to do that. I could do it in the Collided method, but then the sound would be played two times at the same time, since the method was called on both entities.

How do you suggest I do this?

• Maybe collect all collisions each frame and only act on a pair (i.e. treat A colliding with B and B colliding with A as one event). – George Duckett Apr 13 '12 at 14:20
• I already act on pairs, and that's where I basically do: a.Collided(b); b.Collided(a); Although my problem is how I should organize the system for registering such entity-class combinations for events. – Eric McLoughlin Apr 13 '12 at 14:25
• @EricMcLoughlin that's two events. – kaoD Apr 13 '12 at 14:52
• Those events, yeah. But I want to trigger an event for the collision, passing in both entities as well. The question is where do I keep that method? – Eric McLoughlin Apr 13 '12 at 15:43

Add a flag to your Collided method, and when you call a pair of Collided events only have one of them process the sound (AUDIBLE and SILENT are simply constants for TRUE and FALSE):

a.Collided(b, AUDIBLE); b.Collided(a, SILENT);


This method is very simple, but it does require that you are calling the events in pairs... in other words, that they are explicitly called right next to each other for each collision. Another method, and this is similar to what @GeorgeDuckett was suggesting, is this:

a.Collided(b);
b.Collided(a);
Sound.collision(a,b);


Regardless of whether you have the sound code external to the objects or inside them, you will be doing a table lookup in the end... asking the sound system if it has a sound that matches objects a and b in either order. Make sure that this query is order independant... it should return the same result for (b,a) and (a,b). If you will not have every combination possible, you should also have failthrough logic... for example, you might have a generic 'a' sound that you use when there is no specific sound for collisions with 'b' (or vice versa, of course).

Both of these suggestions require locality; they require that you are processing both sides of the collision at once. If your code looks like this you will need a different answer:

for each object
...

object.Collided(other);
end

• I do process them in pairs. The code at the top you're suggesting should work, but what if I want to add sound events between another combination? Then I would either be forced to duplicate sound code or sort the entities so that a certain entity-class would appear on a certain side of the call on every call using that combination. I think I'll actually stick to using the second approach as I thought of myself in the beginning. The problem I have though, is in what class I should keep the two-sided collision callback. – Eric McLoughlin Apr 13 '12 at 15:40
• When you process the sound, it should not matter which object is the caller and which the callee; for example, there should be no difference between CueStick.Collided(Ball) and Ball.Collided(CueStick), as far as the sound is concerned. You should be calling out to a list of sounds that is object agnostic. – Myrddin Emrys Apr 13 '12 at 15:52
• I'm not sure what you mean when you're saying that the list of sounds should be object agnostic. Can you elaborate a bit more? – Eric McLoughlin Apr 13 '12 at 15:56
• I added additional clarification in the answer. The end result is a lookup... a query to see if there is a sound for the combination (a,b). You might, for example, sort sounds alphabetically. In this case, collisions between a Ball and a Stick might be stored as 'CollideBallStick' because you always list them alphabetically (never CollideStickBall). How you organize them is up to you, this is merely one possibility. – Myrddin Emrys Apr 13 '12 at 16:00

I am fairly new to this, but I would make the collided method a trigger for the individual call to each collide. Then you can keep the same call, but it would allow you test for type and then call the sound before each separate collision call is made.

I may be way off base, but they seems like the most logical approach since the sound would need to be triggered once and only when certain objects collide.