Fiery Midi Revenge: A Midi Based Rhythm Game
By Matthew Watson
I always liked music games that make a level out of the song of your choosing. It makes the listening experience interactive and engrossing, and a lot more fun. For my final project, I decided to try my hand at making one of these games using midi song files. With the midi file format the onset of every note is precisely descries, and it makes it possible to make a rhythm game that precisely follows the music.
Most midi files are broken up into a series of tracks. Each of these tracks usually represents and individual instrument in the song. In my midi game, you attempt to play back one track in a song by sliding the player (a little ball of fire) back and forth. If you hit the right notes you are rewarded with points! If you miss the notes the wrong notes will be played back, leaving you with a very ugly sounding rendition of the song.
The position of the fire is pretty forgiving, as long as you are generally close to a note the note will be played. The main challenge of the game is the rhythmic element. When laying out the notes for a track, some limited culling of notes will be done to make sure jumps are not totally impossible. However, some tracks are certainly harder than others to play. In the case that the onset of two or more notes occur at the same time (such as a rhythm guitar track) hitting any note will play the entire set properly.
Any midi song that is a track based midi file can be played. Some midis songs don't preserve separate track information and put all notes together in the file, these files cannot be used for the game. Generally, the main vocal tracks are the easiest to start with. To use the midi executable, call MidiGame with a midi file path as the argument.
The scoring for the game is pretty simple. Each correct note will award you 50 points. String together longer combinations of points, to unlock bonuses.
The game menu for track selection.
An in game screenshot.
There are a number of dependencies for the code of this project.
- Fluidsynth: I use the fluidsynth sequencer for the audio of the game.
- STK: I use ccrma's own Synthesis ToolKit for the midi file parsing. This interfaces with Fluidsynth in Sound.h/cpp.
- Horde3D: I used this game engine for rendering. This is a small and very lightweight game engine with lots of shader support. Turned out to be great for this project.
- GLFW: I used this OpenGL plugin for mouse and input reading as well as setting up the window.
The code is organized with three main parts.
- main.cpp runs quickly and gets the sound and graphics treads up and running, as well as setting up the input callbacks.
- The sound class, sound.h/cpp is really what is calling the shots in the program, I did not want any lag in the audio so it controls the timing of everything. Before playing any new note in the track being played, the sound class will check in with the main game class and check if the user in the right position to play the current note.
- Finally, there is a game manager class (GameManager.h/cpp) which handles are of the rendering on screen and positioning of in game objects. Time is driven forward in the rendering class via updates from the sound class, so it will always be synced up with the song.
The note and pinwheel meshes I modeled myself in Maya. The space skybox I downloaded from opengameart.org. A lot of the code in the GameManager class is modeled after the example code packaged with Horde3D, which I used to learn the engine.
Due to the long list of dependencies, I'm going to try and make a cmake version of my project that can build on any system. Look for this soon!