Somehow despite various things going fairly sideways work-wise and working on setting up a new server at home, I have managed to finish the exercise planned for this week the way I originally intended to! Let the choir of angels rejoice! Somehow I even managed to avoid getting back into engine land for this even though I was somewhat tempted.
Firstly and as a quick refresher, this particular exercise was about adding music and sounds to the game, along with a (persistent) ability to mute the music. I’m not sure offhand if the textbook included the requirement for the mute state, but it seems silly (and annoying) to add music to a game without adding the ability to mute it, and what I learned from ts-tennis is how nice it would be if the state of music could be saved from load to load.
The first thing I did was select some music from incompetech.com (plus a small loop from the same guy on freepd.com) and head on over to bfxr.net to create some sound blips and bloops. I’m by no means a sound design master and having something that’s a nice distinguishable place holder is invaluable. It also helps that the style of sounds you get from that site match the aesthetics of the game.
I went ahead and added in all of the sounds mentioned by the exercise (ball colliding with the walls, paddle and brick as well as something for when you earn an extra life) and also included one for when you lose a ball, since that seems like a good candidate as well.
Music-wise I went the way of Rx and added three songs, one for the title screen, one for the game itself and one for the game over screen. It seems nicer somehow to have something kind of peppy to get you interested in playing, something slower and sadder for when the game is over, and then the actual game theme itself. I think I ended up selecting the same song (Mellowtron) for the game over screen for this very reason.
Once everything was in place, it was a quick matter to include a boolean value that indicates if music should be muted or not and use that to control the music. Since each game state is its own Scene instance, the activating() method starts the song for the current scene playing if it thinks things are not muted, and the deactivating() stops it from playing if it currently is. A key handler checks for the M key and toggles the state of the boolean as well as the current play state of the music.
Since I already have support built in for persisting things to local storage if possible for storing the high score between runs, I also persist the state of the mute boolean as well so that it is remembered from session to session. This is actually the part that I was most excited about because having the music always start on a reload in ts-tennis was annoying but turning it off in code meant having to make sure to not check that change in, which was also annoying.
Just to go the “Extra mile” (and also for testing) I got a couple of speaker icons from game-icons.net and combined them into a sprite sheet which is used to display the current state of the mute flag. This is a nice visual reminder of why you might not be hearing music, or that you could be if you’re not already.
I was sorely tempted to drop back into the engine code and institute a mechanism for the stage being able to store all of your preloaded music files using a string key of some sort, so that the main code could preload the music and all of the scenes could just stop and play whichever ones they wanted without having to load any. I took a quick look at the code in fact, before I decided not to bother.
Not wanting to get bogged into (really) unnecessary engine changes, I just went ahead and had the main code preload the music into a shared array that all of the scenes can use; same effect, not quite as clean looking code-wise, but good enough. Along with this, the sprite sheet for showing the mute state is also global, and there is a global function for rendering it in it’s appropriate state in an appropriate location that all of the scenes invoke in their render methods.
Come to think of it, that’s probably a bug since the GameOver Scene invokes the Game scene’s render() method to display the brick layout at the end of the game, so the icon there might be double drawn.
The next upcoming exercise is setting up the ability to have multiple brick layouts, which should also be easy (except for actually creating the layouts themselves, mind you) because the grid and its setup is already fully encapsulated in a nice way. Probably the trickiest part will be in deciding how/where to store the grid layouts and any associated metadata (i.e. their ordering).
First however, I think I’ll go check on that double render bug.