How to Code a Rhythm Game

So you want to program a rhythm game but you don’t know exactly how to begin? Well, during the development process of my rhythm-based mini-game, Funkbot3000, I learned a few things about creating a rhythm game that might be valuable for anyone looking to code one of their own.

In games that use rhythm as its core mechanic, the most important aspect is detecting if the user executes a certain action in the correct position in time. For example, in games such as DDR, the user must step on positional arrows at certain intervals in the musical sequence in order for the game to register the input as a successful action.

In this post, I will depart some knowledge that I learned while creating a rhythm game that will hopefully help you in your journey of making a beat-tastic love adventure!

First and foremost, it definitely helps (but is not required) to have some musical background. If you haven’t had any experience, you might want to brush up on some of the musical terminology.

BPM (Beats Per Minute)

Regardless if you use a full-length song or a small sound-loop, the most important aspect of any song is calculating its BPM. If the song’s BPM is not provided, the two things that you need to calculate the BPM is the length (in seconds) and the number of beats in the song/loop. Then, to calculate the BPM, you simply use the formula:

BPM = (num beats in song) * 60 / (num secs in song)

The BPM provides a foundation on which you can start testing for user inputs.

Break It Down

In the general case, we can assume that our song is in 4/4 time (also known as common time). What 4/4 means is that the song uses four quarter-note beats per bar.

What you want to do next is figure out how accurate you want your input to be.  Using eighth note seems to provide enough accuracy for most sequences. But depending on how complicated you want your player’s input sequence to be, you might want to go all the way to sixteeth or sixty-fourth if you plan to really punish your players with Yngwie Malmsteen-style arpeggios.

Below is a depiction of how a whole note is broken down.

Musical note values

Register Correct Beats

Now, you want to create a cool button sequence that you want players to press when the song is playing. What you want to do is store all the notes in the song that you want the user to hit in an array.

For example, say thatI have a funky, 1-bar drum-loop. And say when the then song is playing, I want to user to press down on a button every first, second, and third beat in the loop.

If I am using sixteenth notes as my input sequence’s precision, I would create an array like this:

Array beats = [ 4, 8, 12 ]; // 1st, 2nd, 3rd quarter note

So for each quarter note, there are four sixteenth notes.  The array above suggests that we want to detect the first, second and third sixteenth-note of each bar, so we multiply each value (quarter note) by four to get its corresponding value in sixteenth notes.

Detecting User Input

Now that you have your input sequence laid out, you can start detecting if players correctly pressed your sequence in time.

Every time the user hits a button, you must calculate which note (or which sixteenth note in our funk drum-loop example) the input corresponds to. To calculate that, you must know when, in the local time of the song, the button was pressed. What I mean by local time is the current time in the song that your game state is currently at. Say your song loop is only 10 seconds long but the game has elapsed a total time of 14 seconds. That means the local time of the song loop is 14-10=4 seconds.

To calculate the note position given the local time in the song, you can use this formula:

nth sixteenth-note = (time in secs in song) * BPM * (1/60) * (num_vals _per_beat)

In my example, we are using sixteenth notes. Say I have a local-time of 1.5 seconds of a song with 50 BPM. Since there are 4 sixteenth notes per beat, we can calculate the nth sixteenth note:

// BPM = 50, secs = 4, num_vals_per_beat = 4
nth sixteenth-note = (1.5) * 50 * (1/60) * (4) = 5

That means we were at the 5th sixteenth note in the song/loop. Since there is no 5 in our array [4, 8, 12], that means that the user did not press the button at the correct position in time according to what we set as our input sequence.

Go Easy, Bro

We can assume that the user will not press the input button at the exact moment in time that corresponds to your beat sequence (virtually impossible). So, what I did to remedy that is to give an acceptable buffer which provides the user a range of time such that if the user presses the button within this buffer, the game will register the input as correct. For example, if the user presses the button within 0.5 beats of the target beat, the input would register as a success.

So there you have it, a way to structure your code to provide a framework for rhythm games. Now go make some sweet, musical lovin’.


Subscribe to comments Posted on 05.31.10 to Game Development, How To by Eddie
Post Tags: , , , , , , ,

Comments ( 2 )

what excellent understand.

Carline Drake added these pithy words on Jan 18, 2011 @ 8:46 pm

Thank you for this write up; it has helped me solidify some of my ideas. One issue though: if you want to hit the first, second, and third beats then you want the first, fifth, and ninth sixteenth notes. Notes four, eight, and twelve are the last sixteenth notes before the second, third, and fourth beats.

Jon Capps added these pithy words on Mar 18, 2012 @ 10:45 am

Add a Comment


XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">


© Copyright 2012 Illogic Tree | Powered by WordPress | Theme by Zidalgo | Log in