I wanted to add menu sounds to the Game State Management sample code I used in my AppWeek game, to make it play small clicks when changing the menu selection and bigger clicks when moving from one screen to another.
Menu selection sounds were easy: add SoundEffect.Play calls after the selectedEntry-- and selectedEntry++ lines in MenuScreen.HandleInput.
It wasn't so obvious how to add sounds for changing screen. I had maybe a dozen screens to deal with, but it felt like hundreds! If I tried to change each individual screen, I was worried I would miss some places and end up with bugs where one particular menu could be missing a sound if you cancelled it.
How about if I call SoundEffect.Play from the ScreenManager.AddScreen and GameScreen.ExitScreen methods? That catches everything with just two lines of code.
Trouble is, it caught a little too much:
- I got two sounds when loading a game session, first when the LoadingScreen activated, then again when loading finished and the GameplayScreen took over
- I got unwanted sounds when the NetworkBusyScreen went away after network operations such as joining a session
- I got unwanted sounds when my title screen timed out and went to the main menu
- I got unwanted sounds if network errors popped up a MessageBoxScreen
What is the underlying pattern here?
- All these unwanted sounds occur when screens are activated or deactivated due to program controlled state changes
- I only want sounds when screen transitions occur as a direct result of the user pressing a button
I changed the InputState helper to remember whether MenuSelect, MenuCancel, or PauseGame had been pressed within the last frame, and made ScreenManager.AddScreen and GameScreen.ExitScreen only trigger sounds if one of these inputs was detected. I can't make up my mind whether this was a valid solution or an ugly hack (perhaps a little of both?), but it was certainly a tiny amount of code to get the result I wanted!