Juno on the board is a simple endless runner game I made as I was practicing my skills in Godot Game development. Check it out on itch.io below!
You can also enjoy this game on the Google Playstore.
This blog is about my journey of making this project.
The Conception
I had started learning Godot a while back through an online course and made a simple game called Hoppy Days, where we had a cute 2D bunny jumping around the platforms and trying not to fall to its death. Once I finished it, I wanted to try my hand at a project of a similar scale but different enough to be challenging. More importantly, I wanted to use my own characters for the game, for the sake of practice and expanding the Gartage Universe!
Why the endless runner?
It was a tried and tested game design, familiar to casuals and hardcore gamers alike. Simple enough for a starter project but I was sure that implementing a good procedural system would be a fun challenge. Also, one of the main reasons I through Juno on a skateboard is it saves on animating his walk cycle. (I never bothered to make Juno on all fours, and hope I never have to).
The classic mode encompasses the normal endless runner, like Chrome’s Dinorun but the Remix mode is inspired by Catherine’s Babel Arcade mode. Catherine is a fast-paced puzzle game, kind of like solving a rubiks cube while listening to the sticky fingers. It features tough modular puzzles that rack on endlessly as you try to get a high score. I thought implementing this could add a nice twist and challenge to the gameplay. The game design opportunities as well could be interesting, as instead of just jump or duck, the player can choose to jump on certain platforms or not. They can try more high-risk high reward strats as they choose which jumps to make too.
Early Game
On Day 1 I spent time creating Juno’s different animations, the background art and the environment. For Juno’s animations, I used a nice little hack with Blender, where I modeled a skateboard and animated that itself, then used character animator to put them together. For background art, I just made what I learned from the 2D landscape series I did when I started Gartage. I had initially aimed to make it look more Indian with the elements from Indian city architecture, but this turned out to be a challenge as that level of detail was not supported by the art style. So, I just used shades of green to create the vibe of a small Indian city (no logic there to be honest. I just imagined the different colors of India and that popped up, and my art was monochrome, so it was a done deal) The road and objects on the street were just things I pulled from my imagination. Following this, I made the angry cats and spikes. I just made two frames within photoshop itself, so the cats had a nice bounce in their head. Saved a lot of rigging in character animator and at full game speed nobody would notice the fine details anyway.
Making the Basic Game Loop
After I finished making the core art, I started making the base game physics, movement of the player and modular levels. I just pulled in a random road and made sure that each jump played a random animation. Tweaked the jumping, gravity, and movement speed of Juno before making the most programmatically difficult part of the game.
The endless road and enemy generation.
This was an issue because I had not learned much about proceduralism yet and none of the endless runner tutorials on the internet had a method I found intuitive and would work with my overall game design. After hours of pondering, I devised the following system: There would be an array of roads maintained by the main game loop. Every road that goes off-screen will delete itself. On every frame, we check if the number of roads goes below 5. If they do, a new road is spawned a fixed distance away from Juno’s current distance. Similarly, in terms of levels, I made 15 different modular levels for the remix, and a few different enemy patterns for the classic, and the game would spawn one whenever there were 0 obstacles on the screen.
Fixing this was a eureka moment for me as I had devised and implemented a nice, optimized solution that worked well for my game!
Getting the Beats on!
I was able to get a simple prototype of my game made which was sent to my friends with Ridin Dirty playing in the background. This would not fly at all due to copyright issues, so the next step was bringing in music and SFX.
For the music, I spent a few days trying out patterns on my piano, throwing ideas together in LMMS, and making a nice song. I had initially planned to use Indian instruments but could not find a decent sound fount for them. The song’s final version does include sitar in its melody though. I had initially wished to make the music modular and play according to the velocity and score, but this turned out to bring performance issues, and increased storage needs so I ditched it after implementation, which I spent 2 days on :(
I moved onto sourcing SFX from freesound.org and various YouTube channel sfx distributors. Curiously I had the most trouble finding sounds for the skateboard landing, so I ended up with the sounds of a hammer hitting wood. I had to move a lot of stuff around because I liked my sounds in the ogg format for optimal sound and performance, so a lot of trimming and editing went inside of Audition went into this step. I also solved a bug where my LMMS music could only export to .wav format which felt like a huge victory.
The Second Sprint
In the next sprint I focused on making the UI screens, the health system and powerups.
Making the UI screens were simple and mostly about planning the user journey. However, it turned out to be a horrible mess trying to understand Godot’s UI tools to make responsive designs. I did end up realizing how to make responsive touch buttons work on all screens but not something I would wish onto others.
The health system was finally implemented which was an easy addition. The scoring system was not as much. I had a simple score system before that measured the distance the user has traveled, but this did not sit well with my score multiplier powerup which was time-based. How could I only add a 20% increase to the score based on time if the score was just the current position - starting position? Redoing this took an entire day on its own and was quite a tribulation. I ended up making it a function of time, speed, and its previous value.
The powerups turned out to be a collaborative decision, with me getting feedback from my friends on improving the gameplay. They were simple to implement, besides the dreaded multiplier and also switching controls. This really twisted me because the pc port had multiple controls for the same actions and making all of them switch easily was not easy for me. I just did not want to dive into the depths and read the methods within Godot’s Input Singleton and slapdashed a nifty trick to get it done.
The Gamebreaking Setbacks
I think the most difficult part of this project was figuring out how to save and load user scores and make it an easy process in their UX. This was more of a power through the documentation thing as it is a commonly implemented feature.
The most frustrating part, however, was a glitch that caused building to pop in on mobile devices later than they needed to. I had asked the course instructors, communities, discord, and forums and no one had the answer to this question. Solving this problem involved jumping into the depths of Godot. Nobody simply jumps into the depths of a game engine. Anyway, it turned out the Godot will just ignore the in-game camera limits and render things outside it if the user window is wider than the camera. Once I identified the problem, it was fixed simply by reading the documentation and powering forward!
Implementing the verticality of the box platforms was a pain because I had initially not planned what would happen if the player collides with a box. Would they just ram through it, lose health, or teleported above? Would I just place a spring/spike before every box escalation, so the player is forced up? I ended up redoing my entire player physics and movements to incorporate a knock back effect. This big change really opened up the possibilities for game design though! And every time I am up there looking at the skyline with the clouds I am glad I pulled that off.
Fun Times with NPCs
The game was finally in a finished state with the above fixes. However, I really wanted to add wacky background characters and vendors. So I used my road gen features and obstacle gen logic to create add them in procedurally. Some NPCs are rarer than others. Most of them will remind you of some popular Bollywood moments, such as Rancho taking Farhan’s Dad to the hospital on a scooty. Drawing the NPCs and vendors took 2 days, and to be honest was nearing the time I really wanted to move on from this project. I reduced the scope that needed to be added.
But To improve the playability, I had to make the roads wider too, so it can accommodate more people without becoming unwieldy.
In the end just had to tweak them around and the game was ready to be shipped.
Post Production
The game was finally made and released on itch.io. No major problems here, besides all my friends complaining the resolution is all messed up. Took a day in the forge and diving more into the responsiveness of the UI to get that done.
To get the game on playstore however was quite a pain. They rejected it once because it didn’t have the appropriate privacy policy and implementations of it. I ended up using the help of our lord and savior Chat GPT to draft a privacy policy that with few edits got my game on the playstore!
Once this was done, I sent out texts, made a trailer and reels and spread em around like chewing gum in 5th grade.
The Spoils
By the end of it, as of 11th March 2023, my game has a whopping 23 downloads on Google Playstore!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
It also got 75 views on itch.io with 40 people playing it so that is amazing!
It may not be much but at least it is a start, I covered a lot of ground and can finally call myself a game dev worth the salt.
Hope you all had fun reading this dev log! I would love to hear your thoughts on this topic.