Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SFML Game Development.pdf
Скачиваний:
209
Добавлен:
28.03.2016
Размер:
4.19 Mб
Скачать

Cranking Up the Bass – Music and Sound Effects

Music themes

First, we want to play background music depending on the state we are currently in. We have prepared two themes: One for the menu, and one for the game itself. We'll define a corresponding enum:

namespace Music

{

enum ID

{

MenuTheme,

MissionTheme,

};

}

We'll then create a class that has an interface dedicated to music playing:

class MusicPlayer : private

sf::NonCopyable

 

{

 

 

public:

 

 

 

MusicPlayer();

 

void

play(Music::ID theme);

void

stop();

 

void

setPaused(bool paused);

void

setVolume(float volume);

private:

 

 

sf::Music

 

mMusic;

std::map<Music::ID,

std::string>

mFilenames;

float

 

mVolume;

};

 

 

The method names should be self-explanatory. We have a single sf::Music instance that represents the currently-played music. The mFilenames variable maps music

IDs to filenames and is initialized in the constructor. The volume takes a value between 0 and 100; we'll initialize it to full volume. As SFML does not support the MP3 format, we'll use OGG for our files. If you are wondering how to convert between different formats, one possibility is the Audacity software (http://

audacity.sourceforge.net).

MusicPlayer::MusicPlayer()

 

: mMusic()

 

, mFilenames()

 

, mVolume(100.f)

 

{

 

mFilenames[Music::MenuTheme]

= "Media/Music/MenuTheme.ogg";

mFilenames[Music::MissionTheme] = "Media/Music/MissionTheme.ogg";

}

[ 218 ]

www.it-ebooks.info

Chapter 9

Loading and playing

SFML uses the sf::Music class to deal with music themes. As already mentioned in Chapter 2, Keeping Track of Your Textures – Resource Management, this class behaves

differently from other resource classes. Since music themes are usually long and may require a lot of memory, they are not loaded at once into RAM. Instead, sf::Music streams them from the source media, usually the hard disk. This means that only

a short chunk is kept in memory at one time, with new ones loaded as the theme progresses. As a result, the source media must be available for as long as the music is played. For files, this means that you should not unplug an external storage device with the music on it. You can also load resources from different sources such as the RAM; in the case of music, you are responsible for their constant availability.

In the MusicPlayer::play() method, the path of the desired music is looked up in the map. The theme is loaded and possible loading errors are checked. The streaming nature is also the reason why the method of sf::Music to open a theme from the hard disk is named openFromFile() and not loadFromFile().

void MusicPlayer::play(Music::ID theme)

{

std::string filename = mFilenames[theme];

if (!mMusic.openFromFile(filename))

throw std::runtime_error("Music " + filename + " could not be loaded.");

mMusic.setVolume(mVolume);

mMusic.setLoop(true);

mMusic.play();

}

At the end, you can see some new statements. The setVolume() method sets the music's volume to a value in the range [0, 100], with 0 being mute and 100 being the maximum volume. The setLoop() method specifies whether the theme is played again as soon as its end is reached; background themes are usually looped. The play() method eventually starts the music. Since music and sound effects use their own threads in SFML, you don't have to update them continuously. However, you have to keep the sf::Music object alive as long as the music is being played.

[ 219 ]

www.it-ebooks.info

Cranking Up the Bass – Music and Sound Effects

Music themes can be stopped or paused; for this purpose, sf::Music provides the stop() and pause() methods. If a theme is paused, you can resume it from the time where it was paused. A stopped music, in contrast, is replayed from the beginning. If we call openFromFile(), the music will automatically be stopped. The getStatus() method can be used to check which state the music is in. It returns one of the three enumerators in the sf::Music scope: Playing, Paused, or Stopped.

void MusicPlayer::stop()

{

mMusic.stop();

}

void MusicPlayer::setPaused(bool paused)

{

if (paused) mMusic.pause();

else

mMusic.play();

}

Use case – In-game themes

We have seen that using music themes with SFML is very simple. We are now going to invoke the MusicPlayer routines in the different states of our game. First, the

Application class gets a MusicPlayer instance and the State::Context class gets a new pointer, named music, to the music player.

In the menu state's constructor, we play the menu theme:

MenuState::MenuState(StateStack& stack, Context context) : State(stack, context)

, ...

{

...

context.music->play(Music::MenuTheme);

}

We proceed analogously towards the game state, where we play the mission theme:

GameState::GameState(StateStack& stack, Context context) : State(stack, context)

, ...

{

...

context.music->play(Music::MissionTheme);

}

[ 220 ]

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]