Simple sound FX
In this section, we will add three sounds. Each sound will be played on a particular game event, that is, a simple thud sound whenever the player chops, a gloomy losing sound when the player runs out of time, and a retro crushing sound when the player is squashed to death.
How SFML sound works
SFML plays sound effects using two different classes. The first class is the SoundBuffer class. This is the class that holds the actual audio data from the sound file. It is SoundBuffer that is responsible for loading the .wav files into the PC's RAM in a format that can be played without any further decoding work.
When we write code for the sound effects in a minute, we will see that, once we have a SoundBuffer object with our sound stored in it, we will then create another object of the Sound type. We can then associate this Sound object with a SoundBuffer object. Then, at the appropriate moment in our code, we will be able to call the play function of the appropriate Sound object.
When to play the sounds
As we will see very soon, the C++ code to load and play sounds is really simple. What we need to consider, however, is when we call the play function, where in our code will we put the function calls to play? Let's see:
- The chop sound can be called from the key presses of the left and right cursor keys.
- The death sound can be played from the if block that detects that a tree has mangled the player.
- The out of time sound can be played from the if block which detects whether timeRemaining is less than zero.
Now, we can write our sound code.
Adding the sound code
First, we will add another #include directive to make the SFML sound-related classes available. Add the following highlighted code:
#include <sstream>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
using namespace sf;
Now, we will declare three different SoundBuffer objects, load three different sound files into them, and associate three different objects of the Sound type with the related objects of the SoundBuffer type. Add the following highlighted code:
// Control the player input
bool acceptInput = false;
// Prepare the sounds
// The player chopping sound
SoundBuffer chopBuffer;
chopBuffer.loadFromFile("sound/chop.wav");
Sound chop;
chop.setBuffer(chopBuffer);
// The player has met his end under a branch
SoundBuffer deathBuffer;
deathBuffer.loadFromFile("sound/death.wav");
Sound death;
death.setBuffer(deathBuffer);
// Out of time
SoundBuffer ootBuffer;
ootBuffer.loadFromFile("sound/out_of_time.wav");
Sound outOfTime;
outOfTime.setBuffer(ootBuffer);
while (window.isOpen())
{
Now, we can play our first sound effect. Add the following single line of code to the if block, which detects that the player has pressed the right cursor key:
// Wrap the player controls to
// Make sure we are accepting input
if (acceptInput)
{
// More code here next...
// First handle pressing the right cursor key
if (Keyboard::isKeyPressed(Keyboard::Right))
{
// Make sure the player is on the right
playerSide = side::RIGHT;
score++;
timeRemaining += (2 / score) + .15;
spriteAxe.setPosition(AXE_POSITION_RIGHT,
spriteAxe.getPosition().y);
spritePlayer.setPosition(1120, 660);
// update the branches
updateBranches(score);
// set the log flying to the left
spriteLog.setPosition(800, 600);
logSpeedX = -5000;
logActive = true;
acceptInput = false;
// Play a chop sound
chop.play();
}
Tip
Add exactly the same code at the end of the next block of code that starts with if (Keyboard::isKeyPressed(Keyboard::Left)) to make a chopping sound when the player chops on the left-hand side of the tree.
Find the code that deals with the player running out of time and add the following highlighted code to play the out of time-related sound effect:
if (timeRemaining <= 0.f) {
// Pause the game
paused = true;
// Change the message shown to the player
messageText.setString("Out of time!!");
//Reposition the text based on its new size
FloatRect textRect = messageText.getLocalBounds();
messageText.setOrigin(textRect.left +
textRect.width / 2.0f,
textRect.top +
textRect.height / 2.0f);
messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);
// Play the out of time sound
outOfTime.play();
}
Finally, to play the death sound when the player is squished, add the following highlighted code to the if block, which executes when the bottom branch is on the same side as the player:
// has the player been squished by a branch?
if (branchPositions[5] == playerSide)
{
// death
paused = true;
acceptInput = false;
// Draw the gravestone
spriteRIP.setPosition(675, 660);
// hide the player
spritePlayer.setPosition(2000, 660);
messageText.setString("SQUISHED!!");
FloatRect textRect = messageText.getLocalBounds();
messageText.setOrigin(textRect.left +
textRect.width / 2.0f,
textRect.top + textRect.height / 2.0f);
messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);
// Play the death sound
death.play();
}
That's it! We have finished the first game. Let's discuss some possible enhancements before we move on to the second project.