Creating my first game
I created my first game! I created "Calm Before the Storm" to submit for the Brackeys game jam, building this prototype in 7 days. I used Godot to create the game. The jam theme was "calm before the storm". Below I will outline the progress I made day-by-day, to get the prototype seen here up and running. First I'll say what I knew before the jam started - I did not feel confident that I knew enough to enter a jam, and maybe this will help someone else take the leap to enter a game jam despite feeling like their knowledge base is too small.
Prior experience: Before the contest began, I had been learning Godot for about two weeks. I started by following Brackeys' Godot tutorial: How to make a Video Game - Godot beginner tutorial. The tutorial is only a little over an hour, but it took me multiple days to follow the steps. After I finished this tutorial and made a basic level, I tried to return and edit my level, but ran into issues. The tilemap node I used was apparently from an older version of Godot and was not the current correct way to do things - which (I thought) made it very hard for me to edit my platformer level. I decided to start from scratch and do the same thing again, building a new level, with new features and expanding on the ideas I was learning. The going was very slow, but very fun and satisfying. By the end of two weeks, I had created a lock that prevented a platform from moving, and created a key that would "unlock" the lock and free the platform once you obtained the key and returned to the lock. I had also learned how to create a ladder zone, where I turned off gravity physics allowing movement up and down with arrow keys. This was the extent of my knowledge going into the jam - two weeks of intense learning and experimenting, with no background coding except for a college intro class to c++ completed almost 15 years ago.
Day 1: Theme was released. I thought about the theme "calm before the storm" for a bit, and came up with the concept of a bad guy that spawns in after a timer counts down, and chases you through a platformer. I did not open Godot on day 1.
Day 2: I created a project. I imported a tileset to use, and I looked on itch.io for an "enemy" asset. I built a basic scene and built a level using the tileset, including adding a key animation to run towards. I created a "player" scene. I built an enemy scene, but he couldn't move yet.
Day 3: I tackled the big mechanic of my game - the enemy. I wanted a timer displayed on the level, counting down. I wanted a bad guy, frozen, until the timer got to zero. Then I wanted the bad guy to chase. I imagined him being on the ground and running/jumping after me. I found some tutorials to follow, but they really showed me how to use a chase function for a top down 2D game without gravity. This is what I ended up using for my game - so my enemy floats, without being grounded. It does avoid obstacles, and calculate a path to the character. The way to do this is by creating a NavigationAgent2D and painting a navigation layer onto tiles you want your bad guy to be able to navigate on. Creating the script for this was the most confusing part of the project for me, as it had me using commands I wasn't previously aware of, and of course I'm still learning the Godot syntax. Once I had the enemy chasing, I saved the enemy scene and added it to my level scene. I added a timer node, and created a signal for timeout() that signaled the enemy script. I used that timer to flip a bool variable from false to true, and nested the navigation agent commands into an if statement. I also created a label to display my timer. To do this, I had to tell the timer to round to the nearest 0.1 seconds - or "snap" to the nearest 0.1 second. I also had to use a script to display the time within the label (label.set_text).
Day 4: Now it was time to figure out how to move from one level to another level. I hadn't done this in my previous learning. I ended up making separate scenes for levels. During this process, I learned that you can make a sort-of template if you know that multiple scenes will need the same "base" - the same assets, label, timer, et cetera. You do this by creating a scene, saving it, then in the bottom left file system, right-clicking on the scene and creating a new "inherited" scene. It turns out when you do this, you are modifying the original scene when you modify the inherited scene, unless you "make local" or clear inheritance. This did lead to a lot of back and forth, and in the end it probably would have been quicker/less confusing to build all my levels from scratch by dropping in my assets and building new pieces, but now that I understand the inheritance system I will better implement it moving forward. Anyway, I did build another level. I did figure out a way to transition from level one to level two when the key was touched - when the key area was entered, I used the command get_tree().change_scene_to_file("[insert path to next desired scene here]"). This worked, but I don't think it's exactly right, because I get a bug every time I use this. Code still works to start the next level, though! I also figured out how to have the player respawn after being killed by contact with the enemy - I instantly transport them back to a specific point. I used the command player.position = vector2(x coordinate, y coordinate). I used the point that I happened to use as my spawn point in level 1. Because this was in my "enemy" script, the spawn "position" is at the same coordinate in all 5 levels. Since I didn't want my enemy to spawn at the same relative spot in the level, but this was baked into my inherited code, I scootched my levels around the level's main Node 2D, to move the spawn to where I wanted it to be on that level. Crude, but, again, it ain't stupid if it works!
Day 5: Running out of days remaining! I had come a long way, but I by no means had what I felt was a game! On day 5 I added 3 more levels. I played around a lot to get things working - getting my levels to link to the next one, making sure all the tiles were within jump height, adjusting my "chase" speed, et cetera. On a few of my levels I placed more than 1 enemy. Day 5 was really fun, because I felt like my game became "fun to play" for the first time! I added a coyote timer, which I had learned while working on my previous project, and I "flipped" the sprites based on direction of movement. This was much more difficult for the enemy sprite than the main character - he had to flip based on if he was facing my character in the X direction, but I didn't want him to truly point towards the player's direction (no up-down turning). After a long time, I figured it out: if (player.position.x - enemy.position.x) >0, sprite_2d.flip_h = false. elif (player.position.x - enemy.position.x) <0, sprite_2d.flip_h. = true. This is a great example of something being way harder than it first appears (at least for me, a beginner). I got the main character to face L/R in minutes. It took an hour or two to get the enemy to face the direction he was prowling in. Tedious yet satisfying.
Day 6: Today I needed to add music and sound effects. This is a category of rating in the competition, and so far my game was silent. I spent some time looking for free audio clips that weren't copyrighted. I wanted the same soundtrack for each of my 5 levels: a calm sound for 5 seconds, a thunderclap, then tense music. I found appropriate music files. When I imported them, I realized I wanted the original file to play for only 5 seconds, then the thunder to play, then to play the final sound, which I wanted to loop indefinitely until the next level started. The tense music I found didn't make a perfect loop, but after listening to it I thought I could splice it into one. I used the program Audacity to create my music. I slightly trimmed the calm intro music so at 5 seconds it hit a nice transition. I added my thunder noise. I exported this combo as one sound. Then, I adjusted my tense music, to create a "song" that I could loop without it being obvious when the loop transition was. I exported the tense music clip. With these two clips in Godot, I created a new scene to have my audio. I set a function to autoplay my initial "song". I created a timer that counted down the time I wanted to pass before starting my tense music. I did it this way because my thunder noise faded out a bit, and so I didn't want to wait until the first "song" was completely finished before starting my tense music. I also added a "jump" sound effect. Finally, I started cleaning up and polishing a bit, making sure my levels were all centered in the camera, adjusting some levels based on gameplay, et cetera. Finally, I exported a file for my friends to playtest. I didn't really know how to do this either, so it took a bit and a little help from my more tech-savvy friends to export. My friends found some important issues. First, my headset must have been turned down when I made the audio, it played a bit too loud during the game for my friends, and there was no way for them to adjust it. Second, my friends found a way to get stuck on the enemy sprite, and get boxed against a wall, unable to move, and not dying. I had NOT found this bug in my playtesting - I think I had gotten good at my controls through incidental repetition from playtesting, and was avoiding the enemy monster too much. I would have had no clue I had this game-breaking bug without having other people playtest.
Day 7: Got to fix that bug. After some investigating, I realized what was happening was that if you die very close to the start, and then you "respawn" by being teleported to the starting coordinates, it is possible for this to happen without exiting and re-entering the enemy kill box. You can just magically stay within the kill box the whole time, thus not triggering a new death. I wasn't sure how to fix this - I also wasn't sure why the player was then getting stuck there - with the enemy still trying to chase to the player, so floating to a wall, and then fully pinning the player. I talked it through with my friend who is skilled in programming, discussing some possible fixes that seemed too complicated to implement on the last day, and that I wasn't sure would even work. I told her I wasn't even sure why the player was getting stuck on the enemy, they shouldn't even be colliding. She asked me to show her how I knew they couldn't collide. During the demonstration of how the player couldn't collide with the enemy we together discovered that, in fact, the player could collide with the enemy. I had placed the player on a collision layer with the tilemap, the player layer, and the enemy layer. Taking the player OFF the enemy layer made it so that my player could no longer be pinned, and could now fall through the killbox of the enemy on respawn, fixing my bug just in time. I turned down the audio significantly. I also added a "You win!" scene, which I played for 3 seconds after beating the fifth level, and a credits scene as well. I got fancy and had my player, and an enemy, spawn into the credits scene, so the game player had something to interact with while thoroughly reading every line of credit. Finally, I exported my game and had a final play-test with my friends. The last challenge was figuring out how to submit to the game jam. Turns out I had to upload the game to my itch.io page. I wanted it to be playable online, not a download, so one final tutorial to figure out how to do that, and I submitted, in time for me to play video games with my friends and spouse, my usual Saturday evening activity.
Overall, I'm quite pleased with how this small game turned out. At the start of the week I wasn't certain I could make a complete game, particularly within the time constraints. I did, and I think it's pretty fun! Thank you to all my play testers. Special thanks to my spouse, who play-tested more times than was fun, and who also had to put up with my divided attention.
I do want to continue improving my game. I've realized I need a menu, to enable restart, optimally to adjust the volume, to maybe show controls/allow you to play specific levels without playing through them all. I want to create more levels, as the game is super short right now. I want to add some animations and maybe improve my sprites. I'd like to add a death counter, to display on the credits page, and maybe a gameplay timer, to make it possible to speed-run the game.
Thanks for reading my devlog about the process of creating my first game. Happy gaming!
Files
Calm Before The Storm
Precision platformer short game
Status | Released |
Author | bacon10bit |
Genre | Platformer |
Tags | 2D, Pixel Art, precision-platformer, Retro, Short, Singleplayer |
Comments
Log in with itch.io to leave a comment.
Very nice. You were able to make some very nice puzzles with a simple concept! Hope you keep on creating.
Happy gaming!