Featured image of post Rhythm Game in C Language

Rhythm Game in C Language

A Rhythm game I created as a 1st-year term project assignment.

Building a Rhythm Game in C

This is the rhythm game I made as a first-year term project.

Making the game itself didn’t take long, but I remember struggling to get the notes in sync.

How to Play

Use the D, F, J, K keys to hit notes.

If you hit a note precisely, the judgment is Excellent. If you hit slightly late, the judgment is Good.

Hitting notes consecutively builds a combo.

Your score increases based on combo and judgment. The scoring formula is:

1
score += (combo / 10 + 1) * 50

In the settings menu you can toggle two options:

  • Turning on Note Recording Mode enables an editor mode.
    The music plays but no notes fall. While the song is playing, your key inputs are saved as notes to a file named note.txt.

  • Turning on Debug Mode enables debugging.
    You can check the screen refresh delay.

Explanation

  • The simple text animation at the start is implemented with a for loop.
    I store the text in a 2D char array and repeatedly print and erase one line at a time.

  • When a song is selected, the program reads a text file containing the notes into a char buffer.
    0 means no note, 1 means a note exists.

  • The music is played using the PlaySound function.

  • Notes are rendered by changing the console text color and printing spaces so they look like rhythm-game notes.
    I change text color with SetConsoleTextAttribute.

  • The per-frame delay is matched to the song’s BPM.
    Because notes must be drawn quickly, delay variance is inevitable.
    I measure time at the start and end of each loop and adjust the delay to keep it uniform.

  • Using a variation of double buffering, I clear only the regions where the front and back buffers differ (with spaces) and then draw.

  • Key input is read with GetAsyncKeyState.
    For multithreading I use _beginthreadex, which allows multiple keys to be registered simultaneously.

  • When a note reaches the judgment line, I compare the screen buffer with the current key state to determine the judgment.
    By comparing the states of the front and back buffers, I distinguish hold notes from tap notes.
    If you press exactly on time, it’s Excellent. If you press early, it’s Good. If you miss, it’s Miss.
    A key_state variable prevents holding a key to farm points.

  • During gameplay the counts of Excellent, Good, and Miss are recorded.
    A rank is assigned based on their ratios.
    When the game ends it shows the judgments and draws a graph so you can see your performance at a glance.

Built with Hugo
Theme Stack designed by Jimmy