Categories
gamemaker studio

Controlling Objects with Rhythm

In this tutorial I’m going to show you one way to control objects in GameMaker Studio with rhythm. This is if you would like actions or code to run along with the beats of music. Please note that this is not about measuring the inputs from the user, but about using a metronome controller to synchronize events.

GameMaker Assumptions

GameMaker Studio defaults games to run at 60FPS. This means the code in your Step events will execute 60 times per second.

So if you create an object that plays music, and then synchronize other objects based on frames (steps) per beat, then things should stay in sync. Right? Wrong! If your game is running at 60 frames per second, you’re only measuring within multiples of 60. Only if your music is running at 120 BPM (beats per minute) are things going to stay in sync.

Beats Per Minute

Music tempo is generally measured in beats per minute, BPM. This is going to vary per song, and sometimes vary within the song itself! Let’s say your music is a little faster than 120, say 130. Then SIMPLIFIED, it would visually look like this:

So how are we going to overcome this obstacle without varying or changing the FPS of the game? We can use the built in function: delta time.

Delta Time

Delta Time (delta_time) is the time passed in microseconds between each step. Our objects can calculate the microseconds passed, and we can script actions so long as we calculate the BPM of the song to the elapsed milliseconds using delta_time.

Using delta_time, we can tell our object to calculate the time between each of those frames.

If difference from the start of the timer to the point of the calculation matches a beat, then we can run some code or execute some scripts. So let’s get started.

Calculating Tempo

Let’s assume we know the tempo of the music for our game, 136 BPM, and that it plays at the very start of the file. (0:00:00)

  • 1 minute = 60,000,000 microseconds
  • 1 beat in microseconds = 60000000 /136 BPM (441,176 microseconds)

This is great, but musically 1 beat is just a quarter note. What if we want craziness happening at all sorts of intervals. It’s easy, we can break it down further by multiplying the BPM division against the number of microseconds per minute!

  • 4note_ms = 60000000 / bpm
  • 8note_ms = 60000000 / bpm*2
  • 16note_ms = 60000000 / bpm*3

The metronome object

Our metronome object is going to keep the beat! We can have this start measuring at the same time our audio is started from another object.

//CREATE
//#######################################
play = false;
bpm = 135;
beat_ms = 60000000/(bpm*3);

note_dtime = 0;   //delta time per note
note_count = 0;   //total count of notes
note_prev = 15;   //previous note count

//these will be our musical triggers!
note_1 = false;
note_2 = false;
note_4 = false;
note_8 = false;
note_16 = false;

We’re going to use the Begin Step event to clear each trigger and reset the metronome. (NOTE: There’s probably a more clever way of counting the notes, but I’m going to do it anyway)

//BEGIN STEP
//#######################################
note_1 = false;
 note_2 = false;
 note_4 = false;
 note_8 = false;
 note_16 = false;
 if (play) {
     note_count = 0;
     note_dtime = 0;
     note_prev = 15;
     play = !play;
     beat_ms = 60000000/(bpm*3)
     exit;
 }
//STEP
//#######################################
note_dtime += delta_time; //add deltatime passed between steps
note_count = round(note_dtime div beat_ms) mod 16  //count notes

//trigger the 16th notes
if (note_count != note_prev) {
  switch (note_count) {
    case 0:
      note_1 = true
      note_2 = true;
      note_4 = true;
      note_8 = true;
      note_16 = true;
    break;
    case 1:
    case 3:
    case 5:
    case 7:
    case 9:
    case 11:
    case 13:
    case 15:
      note_16 = true;
    break;
    case 2:
    case 6:
    case 10:
    case 14:
      note_8 = true;
      note_16 = true;
    break;
    case 4: 
    case 12:
      note_4 = true;
      note_8 = true;
      note_16 = true;
    break;
    case 8:
      note_2 = true;
      note_4 = true;
      note_8 = true;
      note_16 = true;
    break;
    }
  note_prev = note_count;
}

At the beginning of the STEP event we’re adding the delta_time into our variable note_dtime.

The next line is super important. We’re counting every 16 notes in microseconds using the function we used earlier to determine the number of microseconds per note! This is ROUNDED because our game isn’t running at the exact speed of the music. When a new note is incremented, it is the approximate length of time between each beat we measured.

The note triggers

Each note variable will be set to FALSE at the beginning of the step. Then if the note count is incremented, we will set at variable to TRUE.

Other objects in our game can now look at this object and execute code based on when these variables are set to TRUE

And there you have it, a very simple way to keep track of tempo in your game! Let me know if you’re interested in the scripts themselves that you can import into your game!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s