Libgdx version used on this post: 0.9.2 (download)The last change before start implementing the Level screen is to add sound and music to the menu.
- I updated the libgdx JARs and SO files to the latest available.
- The TyrianPreferences is now called PreferencesManager and lives inside the services package.
- In the Tyrian class (our game class) the services are created inside #create().
- In the AbstractScreen class I removed the disposal of the stage, since it was crashing the game in some 64-bit machines. I'm trying to understand this problem in depth, so I hope I can come up with a better solution in the future.
- The ProfileService was renamed to ProfileManager, and now it uses a new file type: local (instead of external). In Android it will resolve to a folder private to the application in the local file system instead of the SD Card's root. This is good for three reasons: (1) when the application is removed, so are these files; (2) the SD Card is not always available; (3) the files are private to the application. In the Desktop it will resolve to the game's root folder.
Sound and MusicThe com.badlogic.gdx.Audio interface allows us to easily handle sound and music in libgdx, and you can get a valid instance just by calling: Gdx.audio. When working with audio it's important to know that:
- All sound and music should be disposed when they're no longer needed.
- Sound instances are fully loaded to the heap and can have up to 1 MB.
- You create sound instances through: Gdx.audio.newSound(FileHandle)
- Music instances are streamed and are paused/resumed automaticaly when the game is paused/resumed.
- You create music instances through: Gdx.audio.newMusic(FileHandle)
- The supported formats for both sound and music are: WAV, MP3 and OGG.
The Sound and Music servicesWhen dealing with basic audio the hard work lies on creating nice services to work with. Given the directives above it would be nice to:
- Create separated sound and music services.
- The music service should allow just one music to be played at any given time.
- The sound service should cache the loaded sounds in order to improve performance by avoiding excessive IO reads. An LRU (Least Recently Used) cache would do the job, since we want to avoid reloading the most played sounds. After searching for some code on the web I came up with this reusable LRUCache class. I also added an eviction listener so I can dispose the sounds correctly.
- Both services should manage the loaded resources, disposing them when they're no longer needed.
- Both services may be turned on/off at any time, and they should respect the volume setting.
Tyrian resourcesThe real Tyrian was made freeware some years ago, so it's very easy to find resources of the game on the web. I found some official sound tracks and sound effects using Google, and edited them a bit with Audacity to reduce the file sizes. We could work with lightweight MIDI files, but it's not that easy to do so because we have to create code that will run only on Android, and code that will run only on the Desktop. Also, we would have to manage them manually, so we're better off sticking to one of the supported formats.
As an example of using the audio module I modified the source code of all screens to play a click sound when clicking on any button, and the Splash screen starts playing the menu music when it's created.