Soundripples

Prepare for a long blog post. Go get some coffee or something becuase here we go (:

Since we make a stealth action game we needed to handle light and sound in a smart way since guards will see or hear you.
Since I already made a blogpost about the light I wont bring it up except small parts of it. This post will focus on the hearing detection of the guards.

What did I need?
Our main character and the guards will emit sounds when to do stuff, like walking, shooting, throwing things or breathing. I wanted different loud sound.
First I thought about making a circle with a specified radius, with the origin set to the entity that emits the sound(check the image) and then check if a specific point(like a guard) was inside the circle. If it was, the guard detected me.

case: What if the guard stood on the other side of the wall next to me?
This was the tricky thing. Since our soundripples did not count walls I needed a way to stop the sound from entering that side of the wall.

This is where the tricky part was borned. I talked about this to Oskar(one of the programmer and lead designer) and he said “What if there is a wall ending not far away from the main character and the guard stood next to it on the other side.”.(see the image for explanation).

Okay, I knew that I had remove the part outside ONLY if that part wasn’t connected to the main part(check image). This is where I started coding.

How I did this:
For this feature I used 3 different external libraries.
First one is ClipperLib which is the same I used for the light engine.
Second one is Thor. Thor is a SFML extension library which has some nice features. The one feature I needed to use was called ConcaveShape. Since SFML only has ConvexShape I could’nt work with indentations. What it does is that it splits the ConcaveShape into triangles(just multiple ConvexShape).
The third I used was Aurora. This was needed becuase without that, Thor can’t survive.

I started of creating a circle when the player emitted a sound and where the player was standing. I used sf::CircleShape. That is very simple. You define radius, position and set origin to center aka, you set origin to radius.

ClipperLib uses a type called Path. Path is a polygon. Nothing else.

What had to be done: Creating a ClipperLib::Path from the sf::CircleShape. Walk trough every point in the circleshape. NOTE! the points is defined in local space. Use its transform to transform it to global coordinates.

Now I had a polygon path ready to be executed by ClipperLib.

But I needed a second one, the walls which the sound can collide with. And because they are not shaped together I needed to make seperate ClipperLib::Path and in the end, merge them together into a big polygon, except for the walls that are not connected to other walls. I need to define a vector of ClipperLib::Path.

What had to be done: Becuase every wall is a sf::FloatRect I could easily translate every point into a ClipperLib::Path. When I’ve looped trough every wall in the game I could ClipperLib to merge them together. Better say: “Merged what can be merged”. Things that cant be merged with something else, will stay in its own ClipperLib::Path. This used union. Union is a speciel clip type used in sets.

Now I had a vector of Polygons ready to be executed by ClipperLib. After this I executed the clipping and the results is one or multiple shapes that was formed by the sound circle. If I just received one shape back, I knew that the single shape was the sounds origin shape.
But if the result was mutliple polygons I needed to know which of them was the players. (see image 3).

I used a algorithm that checks if a point is inside a polygon. If it was, that polygon had to be the shape closest to the player (see image 3).

From here the tricky part died. I wanted to create a polygon from this but I couldnt use ConvexShape because it cant handle indentations(check the image).

SFML does not handle ConcaveShapes on its own I used the Thor library. It’s like boost but for SFML.
What ConcaveShape really does is that it cuts out triangles from the concave shape and creates ConvexShapes from it.
I could do this by hand but its filthy work. Since there are libraries which does this easy there is no need to do work that already exists. Take a look at this for more information about concave polygons.

http://mnbayazit.com/406/bayazit

And of course, here the result(sry for the debug look ^_^).

About Anthon Fredriksson

2013 Programming