
- •Credits
- •Foreword
- •About the Authors
- •About the Reviewers
- •www.PacktPub.com
- •Table of Contents
- •Preface
- •Introducing SFML
- •Downloading and installation
- •A minimal example
- •A few notes on C++
- •Developing the first game
- •The Game class
- •Game loops and frames
- •Input over several frames
- •Vector algebra
- •Frame-independent movement
- •Fixed time steps
- •Other techniques related to frame rates
- •Displaying sprites on the screen
- •File paths and working directories
- •Real-time rendering
- •Adapting the code
- •Summary
- •Defining resources
- •Resources in SFML
- •Textures
- •Images
- •Fonts
- •Shaders
- •Sound buffers
- •Music
- •A typical use case
- •Graphics
- •Audio
- •Acquiring, releasing, and accessing resources
- •An automated approach
- •Finding an appropriate container
- •Loading from files
- •Accessing the textures
- •Error handling
- •Boolean return values
- •Throwing exceptions
- •Assertions
- •Generalizing the approach
- •Compatibility with sf::Music
- •A special case – sf::Shader
- •Summary
- •Entities
- •Aircraft
- •Alternative entity designs
- •Rendering the scene
- •Relative coordinates
- •SFML and transforms
- •Scene graphs
- •Scene nodes
- •Node insertion and removal
- •Making scene nodes drawable
- •Drawing entities
- •Connecting entities with resources
- •Aligning the origin
- •Scene layers
- •Updating the scene
- •One step back – absolute transforms
- •The view
- •Viewport
- •View optimizations
- •Resolution and aspect ratio
- •View scrolling
- •Zoom and rotation
- •Landscape rendering
- •SpriteNode
- •Landscape texture
- •Texture repeating
- •Composing our world
- •World initialization
- •Loading the textures
- •Building the scene
- •Update and draw
- •Integrating the Game class
- •Summary
- •Polling events
- •Window events
- •Joystick events
- •Keyboard events
- •Mouse events
- •Getting the input state in real time
- •Events and real-time input – when to use which
- •Delta movement from the mouse
- •Playing nice with your application neighborhood
- •A command-based communication system
- •Introducing commands
- •Receiver categories
- •Command execution
- •Command queues
- •Handling player input
- •Commands in a nutshell
- •Implementing the game logic
- •A general-purpose communication mechanism
- •Customizing key bindings
- •Why a player is not an entity
- •Summary
- •Defining a state
- •The state stack
- •Adding states to StateStack
- •Handling updates, input, and drawing
- •Input
- •Update
- •Draw
- •Delayed pop/push operations
- •The state context
- •Integrating the stack in the Application class
- •Navigating between states
- •Creating the game state
- •The title screen
- •Main menu
- •Pausing the game
- •The loading screen – sample
- •Progress bar
- •ParallelTask
- •Thread
- •Concurrency
- •Task implementation
- •Summary
- •The GUI hierarchy, the Java way
- •Updating the menu
- •The promised key bindings
- •Summary
- •Equipping the entities
- •Introducing hitpoints
- •Storing entity attributes in data tables
- •Displaying text
- •Creating enemies
- •Movement patterns
- •Spawning enemies
- •Adding projectiles
- •Firing bullets and missiles
- •Homing missiles
- •Picking up some goodies
- •Collision detection and response
- •Finding the collision pairs
- •Reacting to collisions
- •An outlook on optimizations
- •An interacting world
- •Cleaning everything up
- •Out of view, out of the world
- •The final update
- •Victory and defeat
- •Summary
- •Defining texture atlases
- •Adapting the game code
- •Low-level rendering
- •OpenGL and graphics cards
- •Understanding render targets
- •Texture mapping
- •Vertex arrays
- •Particle systems
- •Particles and particle types
- •Particle nodes
- •Emitter nodes
- •Affectors
- •Embedding particles in the world
- •Animated sprites
- •The Eagle has rolled!
- •Post effects and shaders
- •Fullscreen post effects
- •Shaders
- •The bloom effect
- •Summary
- •Music themes
- •Loading and playing
- •Use case – In-game themes
- •Sound effects
- •Loading, inserting, and playing
- •Removing sounds
- •Use case – GUI sounds
- •Sounds in 3D space
- •The listener
- •Attenuation factor and minimum distance
- •Positioning the listener
- •Playing spatial sounds
- •Use case – In-game sound effects
- •Summary
- •Playing multiplayer games
- •Interacting with sockets
- •Socket selectors
- •Custom protocols
- •Data transport
- •Network architectures
- •Peer-to-peer
- •Client-server architecture
- •Authoritative servers
- •Creating the structure for multiplayer
- •Working with the Server
- •Server thread
- •Server loop
- •Peers and aircraft
- •Hot Seat
- •Accepting new clients
- •Handling disconnections
- •Incoming packets
- •Studying our protocol
- •Understanding the ticks and updates
- •Synchronization issues
- •Taking a peek in the other end – the client
- •Client packets
- •Transmitting game actions via network nodes
- •The new pause state
- •Settings
- •The new Player class
- •Latency
- •Latency versus bandwidth
- •View scrolling compensation
- •Aircraft interpolation
- •Cheating prevention
- •Summary
- •Index

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