Created in 36 hours for Dandyhacks '16.

Inspiration

A shared love of both rhythm based games and quick, high-intensity fighting games led to our idea to combine the two in a way that highlights the strengths of both: the musicality and fun of a rhythm game with the strategy and reflex dependence of a fighting game.

What it does

Rhythm Fighter is unique as a fighting game in that it only lets players act at specific times. These times are determined by pre-programmed beatmaps for each song in the game. Imagine it like Guitar Hero or Rockband, but instead of trying to get all the notes, you are trying to take advantage of the notes as time slots in which you can attack, block, or execute part of a combo. This forces the player to react to incoming beats dynamically. Instead of telling the player which buttons to press at each note, we give them the freedom to choose, thus molding their own style of fighting to the music.

How we built it

Rick: My role was to code up the framework that tied the program together. I coded most of the main game loop and several of the necessary classes to make things work. A good portion of my effort was put towards finding the best way to display all of our graphics in a fast and efficient way. For this, I chose Java's Swing library primarily because of my previous experience with it. The game displays all of its graphics by drawing directly to one of two buffered images: the background layer and the active layer. The background is written once and not touched again unless the game changes screens(from menu to game, etc.) while the active layer is rewritten every update cycle. I chose a Swing Timer to keep track of our framerate, calling an update method every 16 milliseconds for a full ~60 FPS. It's not the most rock solid timekeeper in the world, especially for a rhythm-based game such as Rhythm Fighter, where everything needs to be as in sync as possible to ensure things don't break down. This made the moving bars that represent the beat reach their destination horribly off time. So, to counteract this, Trevor and I developed a function that gives the x-coordinate where every given bar needs to be at the current time so that it reaches its destination at the precise millisecond its supposed to. The result is a rock-solid rhythm game engine that dynamically corrects inconsistencies in the framerate so that each bar is on the beat no matter what. I also spent a lot of time debugging weird issues and implementing Ben's assets into the code.

Trevor: I worked on the character animations and integrated them into the main game loop. I created the animations using 2D graphics from the Swing library. This approach was laborious due to it being entirely based on coordinate plane movement. In order to call the animations in the loop, I used tracker variables to store what frame of the animation would be shown that time through the loop. The possible animations are stored in an enum, and which animation is currently in progress is stored in an outer variable, which is updated every time a successful move is done. There was a lot of trial and error involved to achieve the final result which includes special animations for each move, as well as reactionary animations based on player interaction.

Ben: My role on the Rhythm Fighter team was primarily as the "asset guy". This entailed sourcing and creating all the various graphics and sounds for the game, as well as creating the beatmaps. Most of the graphics such as the backdrops and buttons were rendered from .png images that had been created using Photoshop. The animations (with the exception of the stick figures which were handled by Trevor) were simply series of .png images that were rendered in quick succession to create movement. The creation of the beatmaps was done using the audio editing program Reaper, as well as Notepad++ for formatting. I created each beatmap by importing the .wav file of the song into Reaper and "recording" the beatmap by listening back to the song and pressing a shortcut to place a marker in every place I wanted a beat. I typically could simply perform the song and then go back and edit any markers where my timing was notably off. After the beatmap was established in Reaper, I simply extracted the marker positions from the Reaper project save file and used Notepad++ to format them into a simple list of millisecond values.

Challenges we ran into

The most difficult challenge we faced was definitely getting the game to run in sync with the music. On top of just playing the music for the game, we have to identify when exactly the players can input actions, calculate when exactly the music "bars" should appear on the screen in order to hit the judge bar right on the beat, and lastly we have to ensure that those "bars" actually get to the judge bar on the beat. We also have to make sure every step of the process is done as precisely as possible to make the game playable. When we began writing out the game, we stuck with a graphics update loop that was pretty simple and not very stable. We used a while statement that ran the update loop and then waited about 16 milliseconds. This seemed fine when testing out graphics, but as soon as we set it to music, we realized that the graphics were far too inconsistent. We attempted to fix this by associating the framerate directly with the millisecond position of the song at each point. We called our update method every time 15 milliseconds or more passed from our last update, using the song as a timebase. The issue with this was that the audio player we used (Clip) was not very good at updating the position it was currently playing in the song. So we ran into the same problem. Our final solution was to dedicate a thread (using swing.Timer) to calling update every 16 milliseconds so that the time between updates did not vary nearly as much. They still varied, and it was still not a suitable timebase to rely on for time-sensitive graphics like the bars that indicate musical beats. So Trevor and Rick came up with a simple math function to take the song's position and calculate where each bar should be at that millisecond position. This way, the time-sensitive moving bars aren't dependent on the framerate at all, meaning that variations in framerate cause no variation in the movement of the bar, giving us accurate timing. Another difficult part of this challenge was determining when players can input actions. Because players can only use moves on the beat, we had to limit them from entering in anything until those beats. The issue here was that since the song's position was a relatively unreliable source, the "beat" was not always represented in the millisecond position. To solve this, and account for visual lag and reaction times, we set a series of buffers to allow players to input actions during a short range (<100 milliseconds) around the beat. This made the game a little more forgiving and enjoyable, as well as keeping everything on time.

What's next for Rhythm Fighter

We hope to continue pursuing this idea beyond this proof of concept, potentially with the help of APIs such as libGDX or other graphics engines.

Built With

Share this project:

Updates