Infinite Loop - Postmortem Thoughts


Game concept

The theme of this game jam was "Music," and the prerequisite was "Stuck in a loop." Based on this, I came up with the idea of a rhythm based game where you move through a level automatically on the beat. The only player control is pressing space on the beat to jump. At the end of the level, you are automatically transported back to the beginning but the music gets a little faster each time. 

MVP

Since the development time for this was very short, and I didn't have a team, my goal for this jam was to create one functional level. What this meant to me was:

  • A character that moves one tile per beat
  • One kind of obstacle or hazard for the player to avoid
  • One kind of input (space bar to jump)
  • Only able to perform an action within the beat (+/- a certain amount of time)
  • Death or level restart if you run into the obstacle
  • Something that ends the game

Development path

I've never made a rhythm game, and I'm relatively new to Unity development. So after writing up a basic Game Design Document, but before starting development, I found a short tutorial on how to build a basic rhythm game. Specifically, this series "How to Make a Rhythm Game" by gamesplusjames. Going through this tutorial helped me grasp the basic concepts of how to tie music to movement, and made me feel more confident in starting my game. From there, I started working on a very basic prototype using only Unity sprites. My player was a white square, and my platform was a long green rectangle. 

My first goal was to get the square moving a set distance once per beat. I suddenly realized that this game was going to take a lot more thinking about math than I expected. While the tutorial was useful for giving me some idea of where to start, it didn't give me an exact route to implement the movement of my character so I had to think about how to do that.

What I ended up doing was considering how often I wanted the character to move based on a set BPM. If the song was 80BPM, then I figured I wanted to move the character every 0.75 seconds (60 seconds divided by 80 beats). Based on that, I needed some way to track the time passed so I could compare it to the time when the player should move. I ended up with something like this in FixedUpdate():

currentTime += Time.deltaTime;         
if (currentTime >= (60 / beatTempo))         
{             
    currentTime = 0;             
    myRigidbody.MovePosition(new Vector2(
        myRigidbody.position.x + referenceTile.GetComponent<renderer>().bounds.size.x, 
        myRigidbody.position.y));         
}

Each frame, add the time passed (Time.deltaTime) to currentTime. Then, if currentTime is greater than or equal to seconds in a minute (60) divided by the BPM, reset currentTime to 0, and move the player sprite one tile forward. 

I don't think this is 100% accurate to the beat, but it ended up working relatively well so I went with this. Now that I had the basic movement figured out, I started working on a way for the player to Jump on the beat. 

This didn't seem like it would be that much more difficult than the base movement, but I ended up having a lot of trouble with the jump movement, and ultimately didn't get it fully figured out. Initially, I was trying to add "steps" that the player could jump up, but I ran into so many problems with this that I ended up removing them and focusing on gaps with lava to jump over.

Once I had the general jump movement sorted out, I realized that the jumping wasn't quite synced up with the beat. I tinkered around with this quite a bit, trying to make it feel more natural, but I wasn't able to get it working quite right. The code I ended up with was basically this:

if (Mathf.Abs((60 / beatTempo) - currentTime) <= 0.3)             
{
    myRigidbody.MovePosition(new Vector2(
        myRigidbody.position.x + referenceTile.GetComponent<renderer>().bounds.size.x,
        myRigidbody.position.y + referenceTile.GetComponent<renderer>().bounds.size.y
    ));
}

My thought process was that if the currentTime is within +/- 0.3 seconds of the beat time (0.75 seconds based on 80BPM) when the player presses Space (Jump), then the player should jump. Otherwise nothing should happen. 

This works technically, but in reality it doesn't really match up where I would expect as I'm listening to the music. I hear the beat so I press Space, but the timing in code isn't right so I don't jump, which is frustrating. I spent a while trying to edit the jump functionality to feel better because it's the core feature of the game, but I'm not entirely happy with how it ended up. I'm not sure if it's a code problem, or a synchronization problem with the music and when I start tracking currentTime. This is the main thing I would want to come back to in this project, as it's really a bummer to not have the core mechanic of the game work properly.

Various problems I ran into:

  • Player sprite going through the tileset when moving. I eventually figured out that my problem was that I was moving the GameObject.transform instead of using the RigidBody2D.transform. I solved the problem by using RigidBody2D.MovePosition() to move the player sprite.
  • Making the player jump onto a higher tile. The player sprite kept getting stuck on the corner of the tile using RigidBody2D.MovePosition(). After spending a lot of time trying to solve this, I decided to remove this option due to the game jam time constraint.
  • Jump action not timed properly. The jump input doesn't get calculated quite right to match the beat, so the game feels very difficult/broken. I will need to tinker with this more to figure out the right timing.
  • Player movement not timed properly. The movement of the player feels closer to the beat than the jump timing, but it still feels a little off which is frustrating in a rhythm game. Need to investigate this more.

Additional features that would be fun to add:

  • More levels with different design, obstacles, and music
  • Additional controls such as crouching and attacking
  • A point system that scores points when you hit the timing correctly
  • Potential rework of game play. Ideas for this:
    • Arrow system like Guitar Hero and you only move and perform actions when you hit the arrow keys at the right time
    • Tempo bar that you can drag actions onto which will be performed on that beat. Example: You see an enemy that's 5 "beats" ahead, so you place an "attack" action onto that beat

Final thoughts

This is the first game jam that I've participated in, and I stumbled into it a bit late. As a music and rhythm game lover, I really liked the theme of this jam and felt inspired to throw something together. Although the time frame was short, I learned a lot from this project. 

I ran into a lot of frustrations with trying to get the feel of the game right as far as movement and beat. Working on this helped me realize the importance of frame rate, Time.deltaTime, and the order of how code is executed more than other projects I've worked on, as the synchronization between sound, movement, and player input is so vital to this game. 

I also learned some good lessons about scope and time management. I recently learned about Game Design Documents while doing a Unity course, and I was also aware of zoning in on an MVP (minimum viable product). I used a GDD template and tried to keep my MVP extremely simple based on the short time frame. Both of these concepts helped me stay focused on creating a basic, functional prototype of my game idea even if it wasn't perfect.  

Overall, I feel good about what I was able to create in such a short time span and it makes me feel more confident about going into another game jam!

Leave a comment

Log in with itch.io to leave a comment.