# How to add a sound that an enemy AI can hear?

Given:

• a 2D top down game
• Tiles are stored just in a 2D array
• Every tile has a property - dampen (so bricks might be -50db, air might be -1)

From this I want to add it so a sound is generated at point x1, y1 and it "ripples out". The image below kind of outlines it better. Obviously the end goal is that the AI enemy can "hear" the sound - but if a wall is blocking it, the sound doesn't travel as far.

Red is the wall, which has a dampen of 50db.

I think in the 3rd game tick I am confusing my maths.

What would be the best way of implementing this?

-
Do you care about the sound reflecting/reverberating at all? That is, if a section of soundproof wall is directly between the sound source and AI agent, but the wall can be walked around freely, should the AI agent still hear the sound? If the answer is no, then only update each cell once per sound, so the dampening is only applied once to each sound source. If you only have a few AI agents, just trace a line from source to agent. – Sean Middleditch Apr 1 '12 at 10:30
The goal is to have many 'stupid' agents following your sounds around walls and what not. – Chris Apr 1 '12 at 10:46

It seems like a reasonable idea, do remember though, this is a gameplay feature, don't make it more complicated than what is required for gameplay.

I'd change your scheme to have the sound spread immediately, as that is probably easier to program and seems more consistent with the fast spread of real sound.

This is essentially a pathfinding problem, and it's probably best solved using Dijkstra's algorithm. This a one to many point search (one sound source, multiple enemies), and can as such be solved efficiently by starting at the single point.

You start out by doing a spread from the source, and mark all neighbours that have not yet been marked and have a calculated volume above 0, each of those neighbours you add to a list. That list must be sorted by calculated volume. Then you repeat the process for the highest volume entry on the list, adding new entries to the list as necessary, and removing the one you have handled. Repeat until the list is empty.

Whenever you during this process reach a tile with an enemy you know what volume that enemy hears.

-
+1 for immediate sound travel. Unless you are making a physics simulation which cares about that stuff, KISS. – Hackworth Apr 1 '12 at 15:35
Hmmm sounds really good. I also agree with @Hackworth about keeping it simple. The immediate sound was such a 'penny has dropped' moment the minute it was mentioned. I have started reading about Dijkstra's algorithm, but just to confirm, it can include weighted nodes to adjust for different types of walls? – Chris Apr 1 '12 at 21:23
@Chris Yes, Dijkstra's also works with weighted nodes which would be a good way to model walls (eg. the weight will decrease volume etc.) – bummzack Apr 1 '12 at 22:27

I don't think a path finder is necessary, just ray cast to each AI in the area, if there's a wall in the way, they don't hear it. This would work best with some sort of scene graph + spacial partitioning

-
I agree with this answer. – bobobobo Apr 1 '12 at 15:58
That data structure to store the sound will be much simpler this way as well. – Chris Apr 1 '12 at 20:49
I like the idea of a ray cast, but I don't know if that would account for sound passing through different types of walls. For example, a small foot step sound wouldn't pass through the wall, but the sound of a gun firing would. But in this case I don't know if ray casting would sort out those situations – Chris Apr 1 '12 at 21:34
Chris, just take the raycast idea and expand on it a bit. Each time the ray intersects an object, it reduces the volume of the sound by some amount. If the volume is reduced to zero before it reaches the AI, it's not heard. If it does reach the AI, then you have a "volume" value in hand. You can also use this kind of "ray trace with reduction in volume" to apply a sound dropoff over distance. – Tim Holt Apr 2 '12 at 1:30
@Tim Holt - good point, I wasn't thinking along those lines – Chris Apr 2 '12 at 3:54

I think your implementation assumes that the sound level in a cell is cumulative, and that the amplitude simply moves outwards evenly in all directions. Sound doesn't spread out, frame by frame, it's either playing or it isn't, and you want to find out the amplitude to play it at for any given point.

Raycasting through the tiles is one way (and probably the most effective way) of doing it. Just draw a line between emitter and receiver, and subtract the dampening value of each cell along the way. If the number is positive, you play the sound.

If you want to model indirect sound, then you'll have to path-find. Treat the emitter as the root of your tree, and model each adjacent cell as a linked node. Each link has a cost, subtracted from the current volume. Keep traversing through the graph until either you find the receiver or your volume drops below zero (if it does, backtrack and try another path). If there are no paths to the receiver with a positive volume, your emitter can't be heard. NB: you can't just give up traversing when you find the receiver, because there may be multiple paths from emitter to receiver, and you need the one with the highest volume.

If you're modelling AI that care about where the sound came from, the latter approach will help - an AI would be 'hearing' the sound come from direction of the last segment on the path. Nicely, if there are two audible paths to the receiver, they AI could be confused about the multiple sounds and which direction to take.

-
Sound is a wave transmitted through fluid. It might not be appropriate to simulate it that way in a game, but that's certainly not "not the way sound works". – Kevin Reid Apr 1 '12 at 15:45
Fair point, edited – MrCranky Apr 1 '12 at 19:49