__ __ / \./ \/\_ __{^\_ _}_ ) }/^\ / /\_/^\._}_/ // / ( (__{(@)}\__}.//_/__A____A_______A________A________A_____A___A___A______ \__/{/(_)\_} )\\ \\---v-----V-----V---Y-----v----Y------v-----V-----v--- ( (__)_)_/ )\ \\ \__/ \__/\/\/ \__,--'
NAV: [Home] [Games] [Blog] [Videos] [Screenshots] [Art] [Links] [Resources] [Socials] [RIP] [RSS]
So I did it, i entered my first Game Jam, the GMTK Game Jam 2025. I made a game using C and I did not use a game engine. It is a finished, polished game, and you can download it here. You can also get the source code here. This game features soft penumbra shadows, which is not something you usually see even in triple A games. The game is also small enough that a compressed zip or tarball of it can fit on a floppy disk! I was inspired by the demoscene, so I made the "story" about you using a KeyGen. This KeyGen needed your game input to better generate a new random unique key.
Time to get my coffee on!
I had absolutely no plans of entering any game jam until YouTube shown me the video of Mark Brown announcing the start of the jam a few hours ago. I decided immediately to cancel my plans for the next 4 days and get to work. The theme is "Loop" and I spent like 30 minutes in the shower brainstorming ideas, mumbling things like "Your stuck in a timeeee looooop" before deciding on a rhythm game, where each note's "home" pad is constantly moving around screen, in a loop.
So I get to using RayLib with C and build the game out of the Smooth Pixel Perfect example. Day 1 was mostly just set up, I had no actual game play yet. I could build the project in Linux, Windows, and Web(more on that later) and the 4 arrows would be moving around on screen in silence. I also set up my memory management strategy. I have one struct called Game and I have a global pointer: Game *g;
This one struct* contains the entire state of my game. At the start of the game I malloc this game struct and then free it at the end. And that's the memory managed! This game should never have any memory leaks! (more on that later.) Next time I do a game jam, I need to have a game template set up so I do not have to set up all this stuff on the first day.
I spent all of Day 2 working on the game play. Music can be played now, but it didn't match the tempo of the rhythm game yet. The note "home pads" were re-coded so that you give a function the time into the song and it would return the home pad's position. I could use this to both animate the home pads, and also set a note's target position and time. The notes are moved via learping between the spawn position and time with the target position and time.
I set up the timing rules for score counting, and once I had one note working, I made a basic Memory Pool struct for the notes. The Game struct has an array of 256 note structs. Each note struct has a bool for if it's active and a index to the next note. Because the notes are all the same size, its easy to make an allocator. First init each unused note point to the next note in the array. Store an index to the first point in this chain. To use a note, simply set it's isActive bool, and change the "next" pointer to the note's next note. To de-allocate a note its the same process but in reverse. Set the note's next index to the current next, deactivate it, and now you have your new next note.
Next I started designing "Levels". They were first named "Loops" and were going to last until the song, like, looped. But it took too long so that idea was scrapped. Because I still did not have the final song I had no way of knowing when to switch to a different level, so play testing required me to manually change the selected level with each build. I got my friend Rain to play test and give me feedback. The game play was finally here, but it wasn't a game yet.
I started the day playing around with a music tracker for 30 minutes before realizing I do not have the time to compose a song. So I found 2 good songs in public domain that is supported with RayLib's tracker playback. I then sped up the game play tempo to match the song and set up the levels to consistently ramp up with the song's runtime. It felt like a game, but there was still no lose state, you could never fail.
I didn't care, I needed to work on the background. Up until this point the background was solid gray. I spent alot of time with glsl shader code, referencing what I already know with Inigo Quilez's Website and aggressively reducing the resolution until I got something visually impressive that can runs fast on my potato mini PC. If this game can run on my machine, it can run on yours. I wish I had more time to code the graphics, I wanted to have different things have different materials, and I wanted the "Machine Heart" that pulses with the rhythm to be metallic and reflective like a mirror. I also wanted some sort of simulated sky that generated some ambient light. But I didn't get that so instead I made 2 different lights that both cast shadows. Despite this I am still happy with the graphic mage shenanigans I did manage to pull off in a day.
With the game mostly done I really only had 2 things to do: make a lose state, balance it, and then make some sort of start and end sequence. This was tedious and annoying. I thought I would get done early but it took most of my day to make this.
Oh, I also added in a secret I have yet to see commented on. You can play the game using Vim direction keys: HJKL! Good luck to anyone who wants to attempt playing this way!
It was only at this point did I realize how tiny the game file size was, and I decided to make that part of the pitch: "Download less than 1M!". There was a problem though. To make this game I have been only testing with Linux builds. Windows builds were still fine, but Web builds had no background and no sound.
I didn't really have the time to fix this, so I decided to just release on Linux and Windows only. Annoying, but I finally have a finished game and it's time to send it! I spend absolutely no effort on the game page because I'm tired and I got furries to meet IRL tomorrow. Its done and I am very proud of this game!
There are 2 things I did not understand about a game jam: Game jams are about quickly making and releasing a game. You got to make your game look good enough for people to try it. The judges are just randos reviewing and playing your game for the next 4 days, you got to make it look like it's worth playing. And I'm too busy talking to floofs in a diner half way across the state to realize my error and fix it on the first and most important day of judging!
Not only that but people really do not want to download a game to try it out. People would rather skip a download only game to instantly play a web game. I do not know why Game Jams even accept windows native builds of games if they are so disadvantaged when compared to web games!
Also, when I released the source code, I was informed that it leaks memory because I didn't clean up after myself with the RayLib functions a few times. oops.
So because of these mistakes, my game got only 6 reviews, and I was ranked very low.
So I learned my lesson and am in the process of developing a better strategy. Next game jam I enter I will have a template project on my CodeBerg to skip the starting tedium for making a game without an engine, and it will be perfectly playable in and designed primarily for making browser games.
I'm looking forward to my next game jam!
~WR