Introduction to Making a Rhythm Game
(This article was originally a Repl Talk post, I'm just putting it here because it fits the blog.)
Rhythm games are a different genre of video games. Rather than relying on strategy and story, a 'normal' rhythm game is built upon skill and precision. But, at first, making a rhythm-based game may not be so clear without some kind of guidance, hence this tutorial.
But first, let's cover some of the basics.
What is a rhythm game?
A rhythm game is typically structured like this: there is a song playing in the background, and the player has to perform some kind of action to the beat of the music. Take Dance Dance Revolution for example.
The player is supposed to step on the directional arrows on the dance pad according to the arrows on-screen. There are also judgement arrows to indicate when you should step on them. When the arrows on-screen overlap the judgement arrows, that the player's cue to step on the respective arrow. There is also music playing in the background, but since it's a GIF, well, you know.
There are three elements to remember, though:
- Notes (on-screen arrows)
- Judgement Line (judgement arrows)
- Input (the dance pad)
These three elements make up 90% of rhythm games, so make sure you keep them in mind when making one.
Making a Rhythm Game
Okay, with introductions out of the way, let's get to making one ourselves.
Audio File Formats
One of the first things you'll want to focus in on is choosing an audio file format. There are many of them to choose from, but there are a few things to take into account before you go for one directly. First and foremost, what does your language/library support? If you can only use MP3s, use MP3s. If you have many options to choose from, then we can look at some other things.
File loading speed would be another good factor to look at. MP3 files have a bad reputation with loading times, but it's also a lot smaller in file size compared to a lot of other formats. If you have the space, I'd use OGGs or WAVs. I've had a good experience with them overall, so yeah, there's that.
Okay, now that you've got audio file formats out of the way, let's move on to actually getting some maps mapped. If you don't know what a "map" is, it's essentially a fancy term for "level" in the realm of rhythm games. You can think of maps like sheet music, where you have time on one axis and notes on another.
Mapping formats should be readable by a human. Take the .osu file format for example. Each HitObject (what osu! calls notes) contains data for the HitObject's X and Y coordinates, time, effects, and some other information that may be relevant to the note itself. This data is stored in a comma -separated manner, which is something that a lot of other rhythm games follow as well. If you're going to follow this pattern, take a look into your language's string split() function, as it will come in handy.
You'll also want to know if you want to store the note's time in seconds or beats. The upside to using seconds is that you don't have to do any fancy math to calculate when the note should spawn. On the other hand, mapping may not be as easy to interpret (Beat 176 of the song may be at t=41.647937475 seconds of the song, that's no fun.)
The conductor is going to be the central part of your rhythm game. In music, a conductor is the person who keeps time for the rest of the orchestra, and they make sure that everyone is where they need to be. Our conductor is going to do the same thing. It makes sure that the notes spawn at the right time and right place. Here's some pseudocode to follow when making a conductor based around beats:
Let tempo be a decimal value equal to the song's tempo
Let song be a reference to whatever is actually playing the music
On every frame:
onBeat = tempo / 60 * song.positionInSeconds // Convert the song's playback position in seconds to find which beat we are in the song
For each note in the map:
if (note.beat <= onBeat - 4 && !note.hasSpawned) note.spawn()
Note the onBeat - 4 in our if statement. This is to make sure that the note actually spawn before it should be played so that the player actually has time to react to the note (they have the length of 1 measure in 4/4 time for you music nerds)
Sidenote, if you need to find a song's tempo, look it up here
When the player sees a note and presses its corresponding button, you should give a judgement to how well they played that note. You might consider the timing (i.e. how offset they were to the actual note in the song) of the input, the positioning of the input (if you are making a game that has analog input and not digital, like if the game's main input is the mouse or a control stick rather than buttons or keys) relative to the note, or even the manner in which they hit the note (Beat Saber does this. It measures the angle in which you hit the note, and if it was a large enough swing, it awards bonus points.)
This part is not definitive, so do some playtesting to make sure everything feels right.
Another thing I'd like to mention is that there are generally three different scoring methods in rhythm games:
The best one to go with here is accuracy because it gives an almost exact comparison to how the player did to their other scores.
Points can get a bit sketchy when calculating how much the player should get per note. in osu!, a perfect hit awards 300 points, a decent hit awards 100, a crappy one awards 50, and a miss awards 0. This scoring system leans to praise the player for playing the song, whereas accuracy awards the player for doing better than previous notes and punishes them for playing worse. Also, there is a maximum to a score count whereas accuracy fits within the range of 0-100%.
HP is the last scoring method. It is used in games such as DDR (see gif above), SDVX, and Taiko no Tatsujin. This is also a perfectly acceptable way of scoring, as it fits the criterion we're looking for (ranged, award/punish system, etc.) The only complaint that I'd have is that you cannot compare plays to other plays. There is only pass and fail, so if you're going for a more competitive rhythm game, I'd pair this with another scoring system.
That's pretty much all I have for this "lecture". Again, these are only the basics. If you are still stuck on a concept or idea that seems complex, feel free to ask. I've made plenty of rhythm games in the past, so, yeah.
I don't know how to end this, so I'm just gonna link 727pp lol