Beginning C++ Game Programming
上QQ阅读APP看书,第一时间看更新

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.