Design [Programming] Rhythm games, how?

L

Lon-ami

Guest
First of all, what's a rhythm game? Well, pretty much a game where you must follow a beat, which can be constant, or can be determined by specific notes or an instrument. This can translate as a game where you must press a key every second, or a game where you must press a key every time the drums play.

Music-savvy people are probably screaming because I got it all wrong, but still, I think you get the idea.

So, the first thing you need for a rhythm game is a song, or just plain music, providing a track marking the "press key now" moments. I'll call these moments "track points" from now on. So now you need a way to properly read those track points, and then synchronize them with the game, including safeguards to correct small slips on the fly before they pile up and break the game-music synchronization. You also need to determine the lapses of time where the user can press the key.

In my case, to give you a detailed example, I want to make a game where:

  • The track points are marked by an instrument, meaning they aren't constant. So you'll be kinda following the song. This will mean some parts will be slower or faster.
  • You will be able to perform one action per track point. Each action has an animation, that ends right before the next track point. This means these animations (and their gameplay effects) will have to be slowed down or speed up depending on the distance to the next track point. I could have different animations for a single action as well.
  • If animations are to be chained, they need to have a delay, so that the character isn't idle when you press the next action. So you'll use the next action while the previous action's animation is in progress, and your last action won't start playing automatically, waiting for the previous one to finish. This is where things might get ugly.
  • You won't be following the same instrument during the entire song, so the game needs some kind of visual notification for the track points. Its UI representation can vary, but the problems here could come when synchronizing it properly with the rest of the game, and on how to correct the slips without making the UI confusing.
  • The music needs to be looped properly, without breaking the synchronization.

Well, there it is. If you don't understand it too well, think about a dancing game, where actions are dance moves, and you need to dance with the music while using the dance moves you want. These moves will affect the scenario, but they aren't connected to the music in any way, you can play the ones you want no matter what, just respect the track points when activating them.

So, the topic is about how to make rhythm games. The major problem is the music-game synchronization, but things can get uglier if you add more factors like in my example. I've seen stuff around the web, but there's no clear best method. I didn't find anything for GameMaker either.

Would love to hear ideas and suggestions about the topic, specially if you've worked with rhythm games before :D.
 

TehCupcakes

Member
It sounds like you have a good grasp on the design aspects and some of the things you need to look out for. When I made a rhythm game I had a file with track points as you described, and that is basically like a timeline of when the notes hit perfectly. I then worked my way back so that visually as the notes come down on the screen, they are calculating how many steps they have to reach that perfect spot, and adjust their speed accordingly. So basically, let's say that at 120 bpm, your note should move 240px in a second, and suppose your note is a circle with a 120px diameter. I then would take the position of the perfect spot (y = 480) and the time of the perfect hit (t = 1180) and determine when the note should be created. If we create it at -240px, that gives 3 seconds from the time the note is created until it hits the perfect spot. If room_speed is 60, that's 180 steps, so we create the circle at t = 1000. Of course, the frame rate can fluctuate, so after being created the note needs to know the timing of the perfect hit which we established is 1180. Each step, it then changes its speed to accommodate for "slips". I then determined the "ranking" of the hit (e.g. Good, Great, Perfect) based on how far off you were from the perfect hit t value, rather than where the note object was on the screen because that's irrelevant and literally just used as a visual cue.

That was probably the trickiest part for my particular game, and once I got that it worked pretty well. If you're change the speed while notes are on the screen, that can obviously cause the notes to drastically speed up or speed down, so you might want a cue to let the player know a speed change is coming, if possible. As longing as your notes are adjusting speed based on t and not based on the bpm, though, they should line up with the hit point at the perfect time.
 
I

icuurd12b42

Guest
Basic synchronization is done from the music position as opposed to try to synchronize speed movement with the fps and the track length...
track_pos = audio_sound_get_track_position(index);
len = audio_sound_length(index);

for example this should space out notes over 400 pixels for each second of music
y = (note_pos - pos) * 400;

note_pos would be a time in second for the note that needs to play

for the note position you need a separate file or a timeline in that you would read through and set up you note instances or array at the start.

Another method to store note position would be to use tags in the sound file directly but you would need an editor that supports it and a sound engine that can read them, like gmfmodSoundSimple. and come up with a tag system that tell your game what to do, like (GIT A5) (DRUM SNARE) (DANCE MOVE 1) sort of deal. every sound type supports tags. Mainly they are used to display The artist and Sound name... or in web radios, used to make announcements, mini adds and stuff and Karaoke machines use them to store lyrics information.

A separate file has more advantage though. a separate file allows defining the actions without affecting the original soundtrack so if a user has the sound in his collection, all he needs is the separate file. sort of like the closed caption for movies.

Another thing you need to know is GM does not allow playing music files that are not included in the project you need a sound system like gmfmodsimple or other similar engine.

If, like many tried, you want a guitar hero type game where a track, like a guitar goes silent if you miss a note, then you would need to make your own decomposed sound track splitting every instruments... you would start all the sound tracks together and mute the right track when you miss a note.

You can read my GMFModSimple topic See my tools page. pretty much everything that needs say has already been said about music games in there.
 
S

Spikehead777

Guest
It takes a bit of work to make a rhythm game in Game Maker. Let me explain.

For one, it's not too hard to program the individual systems at work--note track file management, audio file management, gameplay mechanics, and drawing--but each one has their own nuances you have to deal with, especially in the context of Game Maker.

You will have to know your own file specification inside and out. Are you saving data similar to a MIDI format, with notes saved per tick, relative or absolute offset, ticks per quarter note, beats per minute, or are you using a simpler time based approach where notes are saved with time and hit points? Are you converting it from one format to another on the fly or on loading? Do you have any special considerations to keep in mind, i.e., Guitar Hero style star power, Rock Band style solos? Each of these points will affect your gameplay mechanics and drawing, but not so much with audio file management.

Just like note tracks, you have to load your audio files into your game in order to hear them. It's easy when you rely on Game Maker's IDE, and if you're using the new and powerful audio engine, you can have samplerate accuracy with respect to the audio file. Essentially, your audio file drives your time variable. Before the new audio engine, you didn't have a way to get the current playback position of an audio file; you were stuck incrementing your own time variable and hoping the game and audio stayed in sync with each other. Using Game Maker's IDE to load music is easy, but what if you want to let users load their own music at any time? You won't be able to use the IDE, and in fact, it gets tricky; you actually have to open and decode audio files into an audio buffer yourself. With .wav files, it's manageable, and you can implement some functions to load them in in about a day. Other formats, like .ogg and .mp3 are even harder to decode, and actually, you don't necessarily have to decode .ogg or .mp3 yourself. You might be able to get away with a command line utility to do the conversion for you, like SoX, but note this won't generally work with all platforms. Personally, I think it'd be a fun exercise to implement the decoding functions myself anyway. =P

Once you have file and audio loading, gameplay and drawing are relatively more simple to do. Gameplay mechanics will be driven by your time variable, and for a "hit note at this time" kind of game like Guitar Hero or Dance Dance Revolution, you need simply just check that your note falls within a given "hit window". A naive implementation would greedily check every note in the track at once and register only those that are valid (e.g., a green note being hit). A better implementation would have a rolling check on a time-sorted list, starting the check from the earliest possible time and ending at the latest possible time (such as a solo where several different notes fall in the hit window at once), and updating your time check as notes are invalidated.

Drawing is still simpler than gameplay mechanics. You would only want to draw relevant notes that are actually visible on screen, so like your time variable, you'd have a time viewing window (minimum visible time vs. maximum visible time, e.g., a window that shows all notes between a time frame of 3 seconds to 5 seconds). Then it's a simple matter of checking your notes to see which notes fall in the time viewing window, and using lerp(a, b, amt) to figure out where in the viewing window the note falls. Note that this does not cover any advanced drawing itself, like using 3D or shaders for effects, but only the basic viewing window. Using 3D or shaders is a subject best left for another topic.

From here, you would link your systems together using your note tracks and the time variable that's driven by your audio engine. Then the sky's the limit. It's up to you where you want to go from here.
 
L

Lon-ami

Guest
Few things for my case:

  • I don't care about the notes themselves, just when they happen. The note type is meaningless. The game will have other elements outside the rhythm stuff that will complicate the gameplay even further already.
  • The game plays to the music, but the music itself is not affected in any way, so I don't need to mute it when the player fails. I might try things like slowdown effects later on, but right now I want a simple prototype.
  • I don't plan for players to use custom music at all, mostly because normal songs might be too fast for the gameplay I'm planning. I'll probably end up making my own music, first a base with the track points, and then extra sound effects. Wouldn't be great but should be enough for the prototype. This could let me use the same fixed track point distances across all the songs, which would simplify things regarding the UI representation of those times, and also let me plan the animations better.

My initial idea (Which is probably not the best one) was to make an array with the timing of the track points.

It sounds like you have a good grasp...
I haven't looked at it too much, but it seems to be easy to work with real time in GameMaker. In other engines you need to calculate elapsed times after each frame has finished rendering, which can be somewhat annoying. Alarms look like classic timers here, or am I wrong?

By the way, for you and anyone else with a rhythm game under your belt, don't be shy and post it here to see it in action :).

Basic synchronization is done from the music position...
Gave it a look, sounds way too complex for what I want (I think). Unless there's a clear advantage for having both the sound and the track points in a single file, of course. There's a lot of license problems talk in your old threads, and I wouldn't want any of that.

I admit though that having the track points marked inside the file could help a lot in case of desynchronization.

It takes a bit of work to make a rhythm game in Game Maker. Let me explain...
No idea about music, sadly. I prefer the time approach, because it can be measured directly with just a timer, but feel free to make me change my opinion if you think the others are better.

The only thing I really want is to note down specific points at the song, and make sure I can react to them from code at the correct time. Pretty much that. I don't want "press the correct note" kind of gameplay. Think of my songs as basic solo drum songs to make things simpler.

So, let's say "A" is press, and "." is dead time, then the track points could be something like: " A . A . A . . . A A A A . . " and then loop. The music can be super complex later on, but the base for the track points is the same.

That part about letting the song drive the time sounds nice, specially because I wouldn't have to worry about synchronization that much. If the song lags or whatever the entire game would so there should be no problems.
 

TehCupcakes

Member
I haven't looked at it too much, but it seems to be easy to work with real time in GameMaker. In other engines you need to calculate elapsed times after each frame has finished rendering, which can be somewhat annoying. Alarms look like classic timers here, or am I wrong?
Alarms tick at the rate of 1 per frame. So if your room speed is 60, setting a timer to 60 is one (theoretical) second. In reality, if the game lags, you will need to compensate for that because the sound file should continue playing at a constant rate even if the rest of the game is lagging. delta_time is your friend.
By the way, for you and anyone else with a rhythm game under your belt, don't be shy and post it here to see it in action :).
Unfortunately, complete games is not something I'm great it. :) I should have said more of a rhythm game engine. I made it in GM8 and I haven't spent the time to port it properly to GM:S, so I'm afraid I can't really show it off. Besides, there's plenty of things I did poorly or that could be done better with GM:S features, so I would want to rework it significantly anyway. XD
My initial idea (Which is probably not the best one) was to make an array with the timing of the track points.
That should work as long as you don't require any extra information about the notes.
 

K3fka

Member
I'm making a rhythm game myself, so I might be able to offer some insight. The way I'm doing things is by piggybacking off of an existing format, .sm files used by StepMania. I actually am working on a library to ease the reading of these files. May or may not work for you, but it's worth throwing out there regardless.

The way things work in my game, I have a timer that I calculate every step using get_timer(). I run get_timer() when I am ready to start playing the song, and store that as an initial offset. Every step I then run get_timer() again and subtract my initial offset from that. I tried using delta time, but I couldn't get it working quite the way I needed, so I went with this pretty straightforward approach instead. Also note I am running my game at a very high room speed (1000). It's early in development so this isn't causing issues right now, but considering most people's monitors refresh at 144Hz max I could easily drop it down significantly if need be once more stuff is eating up processor time during gameplay.

Anyway, another essential piece is nailing down conversion between a beat offset and a time offset. Let's say we have a song running at 120 bpm, and we need to figure out an exact time at which the song will reach beat 3442, for example. If we take the BPM and take its reciprocal, we get minutes-per-beat. Divide that by 60 and now you've got seconds-per-beat, then you can work that into whatever subunit of seconds you're using (since I'm using room speed 1000 I put everything into milliseconds, myself). Finally multiply your beat offset (3442) by this and we get an offset in terms of time. You can then position things based on their time offsets and move them toward the player. You can also go the reverse to get from beat offsets to time offsets.

This post is getting a little technical at this point, probably a bit too technical for this forum, but I'm happy to help you out in PM or whatever. Hope I was able to offer some insight.

Also, icuurd, I have to disagree. I've been able to successfully load audio from external files and play them using audio_create_stream().
 
I

icuurd12b42

Guest
>>Also, icuurd, I have to disagree. I've been able to successfully load audio from external files and play them using audio_create_stream().

Ah, cool to know
 
L

Lon-ami

Guest
Alarms tick at the rate of 1 per frame. So if your room speed is 60, setting a timer to 60 is one (theoretical) second. In reality, if the game lags, you will need to compensate for that because the sound file should continue playing at a constant rate even if the rest of the game is lagging. delta_time is your friend.
So there aren't real time timers here either. Seeing how many engines don't allow them I'm starting to think it's related to performance issues.

I don't like delta_time because I'm a sucker for surgeon precision, but well, I'll deal with it!

Unfortunately, complete games is not something I'm great it. :)
Sounds depressingly familiar xD.

That should work as long as you don't require any extra information about the notes.
The basic idea would be to start a timer when the music file begins, and then when you press a key, check the elapsed time and compare it to the array with the track points. And then reset it properly when the song is over.

Ideally there would be some class or file format allowing sound to send other signals as well. So as music is playing, the sound file is also sending console messages of some sort which the game detects as their own inputs. Sending a true/false boolean every beat would be enough. Everything in one file, so you can edit the song and update the boolean messages easily. Don't know if anything like this exists, or if it could even work with any engine at all.

I'm making a rhythm game myself, so I might be able to offer some insight. The way I'm doing things is by piggybacking off of an existing format, .sm files used by StepMania. I actually am working on a library to ease the reading of these files. May or may not work for you, but it's worth throwing out there regardless.

The way things work in my game, I have a timer that I calculate every step using get_timer(). I run get_timer() when I am ready to start playing the song, and store that as an initial offset. Every step I then run get_timer() again and subtract my initial offset from that. I tried using delta time, but I couldn't get it working quite the way I needed, so I went with this pretty straightforward approach instead. Also note I am running my game at a very high room speed (1000). It's early in development so this isn't causing issues right now, but considering most people's monitors refresh at 144Hz max I could easily drop it down significantly if need be once more stuff is eating up processor time during gameplay.

Anyway, another essential piece is nailing down conversion between a beat offset and a time offset. Let's say we have a song running at 120 bpm, and we need to figure out an exact time at which the song will reach beat 3442, for example. If we take the BPM and take its reciprocal, we get minutes-per-beat. Divide that by 60 and now you've got seconds-per-beat, then you can work that into whatever subunit of seconds you're using (since I'm using room speed 1000 I put everything into milliseconds, myself). Finally multiply your beat offset (3442) by this and we get an offset in terms of time. You can then position things based on their time offsets and move them toward the player. You can also go the reverse to get from beat offsets to time offsets.
So you have a room in a high speed working pretty much at real time? That's clever, but it's true it could be bad for performance. Unless... Can you have a secondary room open, sending data to the main room? Don't think so, but would be cool as a sort of cheat.

Most music programs let you see a timeline in seconds as well, so I wouldn't need to mark down the beats themselves, I could just note down exact milliseconds and then work with those.

This post is getting a little technical at this point, probably a bit too technical for this forum, but I'm happy to help you out in PM or whatever. Hope I was able to offer some insight.
If you think it could be interesting for more people searching help on the topic, don't be afraid and go for it. One of the biggest problem about making rhythm games is the lack of technical information about them ^^.
 

Fern

Member
I think everyone here is over complicating this. I am currently working on a rhythm game so I have a bit of experience here.

1. Delta Timing
2. Play the audio
3. Pre-designated note positions
4. Note movement based on delta timing

That's it.

Game freezes, either the audio will stop and the notes or the audio will keep going and the notes will jump forward.
 

K3fka

Member
Best values and time values are interchangeable assuming you have the info on bpm changes and whatnot. StepMania simfiles indicate notes on kind of a timeline of measures, and BPMs and Stops are stored elsewhere in the file. That information can be combined to convert a beat to time if desired.

Of course you may or may not use a format similar to this one, so it may not be completely relevant to you.

As far as room speed goes, it doesn't really matter because I'm using get_timer() which pulls time independently of room speed (although of course the timer will only be queried every step, which is limited by room speed). I could drop my room speed to half of what it is or less if there are performance issues. I'd recommend a minimum room speed of 144 since the highest refresh rate you'll encounter somewhat often will be 144 Hz.
 
M

mshalojones

Guest
Hi

I'm trying to make my own rhythm game where you trigger the sounds with buttons, matched to the visuals. I'm finding it hard (it's my first Game Maker project and I can't code... yet) but I think most of the problem is related to the length of the audio clips and timing them to particular animation frames. Do you guys have any advice on this or can point me to any related tutorials / tools? It would be very much appreciated :).

Thanks!
 
Top