This is the multi-page printable view of this section. Click here to print.
Game Jams
A surreal racing experience for GMTK Jam 2025 | InsomnaKart
Here we go again
As part of my effort to participate in more game jams this year, I entered GMTK Game Jam 2025 immediately following Kenney Jam 2025. Unlike Kenney Jam, going in, I didn’t have a strong desire to make any particular genre; however, I did know that despite being a four day jam, I wouldn’t be able to work more than about two days due to other obligations.
Planning
When “loop” was announced as the theme, I started with a mind-map and widdled that down to just two ideas:
- A racing game where you’re trying to hit obstacles on the track (heavily inspired by the rush hour mode of Jak X: Combat Racing)
- An RTS with a tech tree where time resets when you die but you keep all your materials allowing you to advance more each run
Having just finished my Riverworld modding tools, I really wanted to make an RTS but decided the content and AI would be too much for me in 48 hours. The racing game seemed easier since it didn’t necessarily require AI.
Being a fan of Jak X, and the intense sense of speed it gives, I decided to mimic its controls for my game. To that end, I planned for a boost mechanic which I would encourage players to use by multiplying the score of a hit obstacle with each lap and a power-slide mechanic which would be required to navigate hairpin turns in the track. I also planned for a weapon power-up which would give the player a larger hitbox on demand; however, this was ultimately cut for time.

Final gameplay
Development
Architecture
Like Maximum Voltage, I heavily leveraged a component-based architecture for my game; however, I decided to try a different approach to components that I had seen in a YouTube video. With my previous games, each component was its own class which often led to duplicate code for components that reacted with an area in the environment. For example, Maximum Voltage’s battery pickup and intel pickup components both had logic to kill an attached health component on activation. Based on this, I decided to apply a behavior-based pattern to interactable components in this game.
I created a base InteractionComponent
which would detect a collision with an area and pass the area to a custom behavior resource’s interact_with
method. The base component had all the logic to disable itself on use but deferred to the custom behavior resource for what would actually happen when it was triggered. I used this system to implement checkpoints, boost pickups, and the out-of-bounds respawn. In theory, this seemed like a good idea but in practice it made the code more complex for little benefit.
The main problem with this pattern is there’s no good way to connect the custom behavior resource to other components of the parent object. For example, the out of bounds component ideally needs a reference to the player it is attached to so it can trigger a respawn but it isn’t easy to pass a reference to the player node into a resource since that resource then becomes scene-local and can only use node path references. For similar reasons, the parent object can’t easily connect to events from the behavior if the behavior was created through the UI. It’s not impossible to do with this pattern but is messier than I’m personally comfortable with.
I think this new pattern has merit in systems where the base component has references to everything the behavior could need (ex where the behavior describes a type of projectile, spell, etc) but I don’t think this pattern works as well when each behavior has dependencies on different things.
Player controllers
Movement
The player movement is largely based on the KidsCanCode Arcade Style Car but I did make a few changes:
- Tweaked various base physics settings
- When reversing, the steering direction is inverted
- The maximum speed is limited using the
_integrate_forces
function - The turn speed, angular damping, and amount you can accelerate and turn is modified when power sliding
- The maximum speed is increased when boosting and the acceleration is instantly max’d out
This worked relatively well but I did find it very difficult to tune given the number of parameters available. It also has an annoying quirk that the player will slowly slide off sloped surfaces.
Camera
Even while boosting, the player never actually moves that fast. Instead, the sense of speed comes from a few camera tricks I learned from playing Jak X during the jam.
Since the game is running in Godot’s compatibility mode, effects like camera blur aren’t available. Normally, I’d mess with the camera’s FOV to give the impression of speed but I noticed Jak X has the same limitations but a different solution. Instead, at a certain speed threshold it drops the camera lower to the track. Because the track is textured, getting closer to it makes it look like it’s moving by quicker. This effect was very easy to implement and I find to be less jarring than altering the FOV.
The next trick is having the camera pan left/right from a point in front of the car/bed while turning. I defined a curve which, based on how fast you’re going, determines how far in the opposite direction the camera will pan while turning. Since the camera pans from the front of the car, it gives the effect that you’re drifting more than you actually are and gives a sense of weight to the car.
Checkpoints
Based on how I’ve heard other racing games work, I implemented a checkpoint system to determine whether the player legitimately completed a lap. Along the track are Area3Ds which you must pass through in sequence to activate the next. A checkpoint will not register if it is not active and will not become active unless the previous checkpoint was passed. Passing the last checkpoint triggers a signal that a lap was completed and starts the sequence over.
The same checkpoints are also used to trigger the enemy spawners located along the track. This was meant to help pace the enemy spawns but didn’t work so well in practice.
This system was incredibly simple to implement and would have served to help with player respawns if I had time to finish that system (as-is, the player always respawns at the start of the lap). I definitely want to explore this system more in future games!

Each rectangle is a checkpoint and the spheres are enemy spawners
Design pivot
Saturday afternoon, I had all the gameplay features implemented and asked my friend James to help with beta testing. Right away, I realized there was a problem when I had to explain that your goal was to hit the memories rather than dodge them. There was no obvious connection to the theme to guide the player to that objective nor did I have time to make a cutscene.
As James played, he noted that he was having difficulty aiming for the memories. At the same time, I was playing and noticed I was gravitating towards dodging memories to get higher lap multipliers rather than trying to hit them. At that moment, I realized the core concept was flawed and that it would be more fun and better aligned with the narrative to have the player dodge the memories.
Thankfully, the component architecture made it easy to move scoring to the boost pickups and within a couple of minutes I had a new build which was much more fun to play. Unfortunately, I think I was still too hung-up on the scoring system to recognize that I should have made other gameplay changes but I’ll save that discussion for the post-mortem section.
Time allocation
Unlike Kenney Jam 2025, I didn’t bother putting together a schedule since I wasn’t sure exactly how much time I’d have to work on it; however, I did track my time throughout the jam for those curious.
Expand devlog
- Wednesday
- 12:15: Project setup
- 12:25: Theme planning
- 13:48: Break
- 19:03: Planning
- 19:11: Player controller
- 20:04: Learning how to import/retarget animations
- 20:50: Sleep
- Thursday
- 21:00: Camera controller
- 23:02: Finding music
- Friday
- 00:12: Checkpoint component
- 02:00: Interaction component
- 02:30: Player controller
- 03:30: Sleep
- 19:10: Game events
- 20:00: Break
- 23:00: Pushable component
- 23:20: Health/death components
- 23:30: Score component
- 23:36: Game timer
- Saturday
- 00:00: Enemy animation
- 00:14: Break
- 01:20: High score system
- 02:00: Sleep
- 10:00: Boost & game feel
- 10:56: Boost pickup
- 11:45: Lunch
- 12:00: Boost pickups
- 12:31: Track
- 13:08: Break
- 13:45: Enemy AI
- 13:50: Break
- 15:10: Enemy spawner
- 15:30: Game feel
- 17:53: Beta testing
- 19:53: Polish visuals
- 21:48: Break
- 23:00: Menus
- Sunday
- 03:00: Audio
- 03:59: Visual effects
- 05:00: Bug fix
- 05:15: Break
- 06:09: Visual effects
- 08:00: Polish
- 09:39: Jam page
- 11:28: Done
Expand time summary
Task | Details | Minutes |
---|---|---|
Planning | Ideation | 83 |
Planning | Schedule | 8 |
Planning Total | 91 | |
Project Setup | Godot setup | 10 |
Project Setup | Animation import workflow | 46 |
Project Setup Total | 56 | |
Code Code | Health/death components | 10 |
Code Code | Game events | 50 |
Code Code | High score system | 40 |
Core Code Total | 100 | |
Mechanics | Camera controller | 170 |
Mechanics | Checkpoint component | 108 |
Mechanics | Interaction component | 30 |
Mechanics | Player controller | 113 |
Mechanics | Pushable component | 20 |
Mechanics | Score component | 6 |
Mechanics | Game timer | 24 |
Mechanics | Boost pickup | 136 |
Mechanics | Enemy AI | 5 |
Mechanics | Enemy spawner | 20 |
Mechanics Total | 632 | |
Game Loop Bookends | Menus | 240 |
Game Loop Bookends Total | 240 | |
Level Design | Level design | 37 |
Level Design Total | 37 | |
Beta Testing | Beta testing | 120 |
Beta Testing Total | 120 | |
Bug Fixes | Bug fix | 15 |
Bug Fixes Total | 15 | |
Balance | Game feel | 143 |
Balance Total | 143 | |
Audio | Audio | 59 |
Audio | Finding music | 22 |
Audio Total | 81 | |
Polish | General polish | 99 |
Polish | Visual polish | 301 |
Polish Total | 400 | |
Jam Submission | Itch page & Submission | 109 |
Jam Submission Total | 109 | |
Break | Break | 819 |
Break | Sleep | 2870 |
Break Total | 3689 | |
Total | 5713 | |
Dev Total | 2024 (35% of allotted time) |
Tellingly, I managed to spend 5 fewer hours working on this game than my submission for Kenney Jam 2025 despite having double the time limit.
Post-mortem
Results
Of the 9,643 final entries and 197k ratings, I received 25 ratings and the following ranks in each category:
Category | Rank | Rating |
---|---|---|
Narrative | #1502 | 3.00 / 5.00 |
Enjoyment | #3667 | 2.96 / 5.00 |
Creativity | #3875 | 3.28 / 5.00 |
Audio | #4461 | 2.64 / 5.00 |
Artwork | #7159 | 2.16 / 5.00 |
I actually didn’t think my narrative was all that clear this jam so I’m incredibly shocked that I ranked in the top 16% for that category! Despite not ranking that high in enjoyment or creativity, I am also really happy to see that my ratings weren’t too bad.
The most common feedback I got was that people liked the humor/narrative and thought the game was fun; however, many felt the steering and braking weren’t responsive enough and that it was too hard/unfair to dodge the memories. Based on the rankings, I can also see that audio and visuals were not well received which isn’t surprising given I didn’t leave myself enough time at the end to polish them.
You can play IsomnaKart on Itch.io but I recommend some of my favorite submissions instead:
Observations
Being the first time I’ve taken place in the GMTK jam, I thought I’d take some notes about how it differs from the other jams:
- Nearly every category winner was download-only - my previous experience has been that downloadable games don’t do as well
- Only half of the category winners were made by teams
- The level of polish for winning games was nearly the same as commercial releases
- Most people were not, or at least did not appear to be, using pre-made assets
- Most games were much longer than 3-5 minutes - some even taking half an hour or more to complete
Pros and cons
Pros
- Recognized the original concept wasn’t engaging and pivoted to what felt fun
- Slide/boosting around corners and off edges is extremely satisfying
- Love how the brain pickups look
- The Godot Road Generator plugin worked flawlessly
- Audio levels were correct this time
- I think having a gif on the jam page helped explain the gameplay
Cons
- Game was severely underpolished even by 48 hour jam standards
- The intro cutscene is awkward and jank
- Connection from the theme to the gameplay isn’t great
- Impossible to dodge without holding boost
- The way I intended the game to be played isn’t obvious to everyone (ie holding boost all the time)
- Random spawns meant not everyone had a good first experience and made the skill ceiling low as scoring high is purely random
- There isn’t much score variation between runs making it feel like you can’t improve
- Using an in-editor thumbnail for the submission page just doesn’t look that good
- I spent way too much time taking breaks
What I would do different
I believe I was right to pivot the game idea when I did but in hindsight I don’t think I pivoted enough.
When the game was based on hitting the memories, the heavier steering, random enemies, and score-based gameplay made more sense since you wanted to hit as many as possible. When changing the game to avoid memories, I should have also made the steering more responsive and the enemy spawns more predictable so dodging was skill-based.
I also think it was a mistake to stick to score-based gameplay. It would have fit better with the narrative to have the game be a time-trial where you’re trying to complete x laps as fast as possible. I could have also changed the timer to count up from midnight to the morning to represent your character struggling to fall asleep.
Artistically, I really want to make games that look and feel like they were released for the PS2 which is why I used one of the PS2’s resolutions for this project; however, the pre-made assets I was using just don’t look as good at that resolution without more advanced visual effects like tilt-shift and dynamic lighting. This is something I already knew but neglected for this jam. Until I can make my own PS2-style assets, I should probably stick to more retro-inspired theming since it works better with the simpler assets I have access to.
With the jam page, I want to get away from using in-editor screenshots for the thumbnail. It just doesn’t look as polished as what others are producing and I beleive it’s limiting how many people choose to play my games.
All that said, I’ve got other projects I want to spend my time on so I won’t be updating InsomnaKart but I will try to remember this for the next jam.
I made a rail shooter for Kenney Jam 2025 | Maximum Voltage
Practice. Practice. Practice.
Since Scream Jam 2024, I’ve been creating tons of small prototype projects in Godot to better learn the engine’s features. Since I wanted to focus on the coding, I’ve been using Kenney assets exclusively for these projects so I was really excited when I learned that Kenney has a yearly game jam!
Preparation
After not doing so well in my last 7 day jam, I was extremely nervous to try a 48 hour jam but decided to make the best of my time by reviewing Adam Younis’ jam devlogs for tips before the jam. I took away two points from his devlogs: make a schedule and prioritize tasks. To that end, I put together my own general purpose schedule for a 48 hour jam based on my best guess at how long each task would take. The exact time spent on each task isn’t that important but the order I work on them was carefully chosen to get the game playable as early as possible.
Expand schedule
Day Time Goal Actions Friday 11:00 AM Ideation Brainstorming - Concept Design Friday 12:00 PM Systems Mechanics - Core Loop Friday 01:00 PM " Friday 02:00 PM " Friday 03:00 PM " Friday 04:00 PM Game Playable Friday 05:00 PM World Design Friday 06:00 PM Core Animations Friday 07:00 PM Game Loop Bookends Score - Win Condition - Loose Condition Friday 08:00 PM Level Design Friday 09:00 PM " Friday 10:00 PM " Friday 11:00 PM " Saturday 12:00 AM " Saturday 01:00 AM UI Design Saturday 02:00 AM " Saturday 03:00 AM Game Complete-able Saturday 04:00 AM Juice Saturday 05:00 AM " Saturday 06:00 AM " Saturday 07:00 AM Story Saturday 08:00 AM SFX Saturday 09:00 AM " Saturday 10:00 AM Music Saturday 11:00 AM " Saturday 12:00 PM Beta Test Saturday 01:00 PM Collectables/Extras Saturday 02:00 PM " Saturday 03:00 PM " Saturday 04:00 PM Title Screen Saturday 05:00 PM Settings Menu Saturday 06:00 PM Credits Saturday 07:00 PM Cutscenes Saturday 08:00 PM " Saturday 09:00 PM " Saturday 10:00 PM Create itch Page Saturday 11:00 PM " Sunday 12:00 AM Testing Test Game in itch Sunday 01:00 AM Create thumbnail Sunday 02:00 AM Screenshots Sunday 03:00 AM Submit Sunday 04:00 AM Sunday 05:00 AM Sunday 06:00 AM Sunday 07:00 AM Sunday 08:00 AM Sunday 09:00 AM Sunday 10:00 AM Sunday 11:00 AM DEADLINE
After building the schedule, I finished my prep for the jam by downloading every Kenney and Kay asset pack and importing them into a file manager called Eagle. Eagle is a program I learned about last year from a YouTube video on tag-based filesystems and I’ve been using it ever since to help organize my game assets (not sponsored, I just really like it). The nice thing about Eagle is that it lets you assign tags to your assets and search for them much easier than through Windows Explorer. I figured having the files indexed would help me find what I need during the jam quicker.

Searching for Kenney and Kay assets in Eagle
Ideation
Before the jam started, I had been on a rail-shooter kick playing games like Starfox 64 and Galaga: Destination Earth. Having seen the ships in the Kenney Space pack before, I really wanted to try making a game like these and was thankful when power was announced to be the theme. Immediately, I decided that I would build a 2-3 minute rail shooter where the player fires electrical bolts and can charge their ship to either unleash a more powerful attack or dodge. I figured this idea was perfect for a short jam since player and enemy movement could be done entirely with Path3D
nodes.
Being inspired by retro rail shooters, I also decided the game would run in an extremely low resolution (256x224) and adhere to the simple geometry and colors of a SNES SuperFX game.
Development
Component architecture
I’ve been working to embrace component architecture more in my recent games so I started by defining a whole set of reusable components for every game function I could need: health, hitboxes, hurtboxes, scoring, item pickups, damage/hit effects, etc. These components are so generalized that almost every object in my game was built from the same components.

Charge ring components

Enemy components

Player components

Projectile components
Most components are also written in such a way that they can take references to other components to chain behavior without needing any code. This is done by having the components self-subscribe to the linked component’s signals on ready. For example, the pickup component will kill a linked health component when obtained and the death component will destroy an object when its linked health component is killed.

Example death component

Example flash component

Example hit-box component

Example hurt-box component

Example score component
Player controllers
Both the player and enemy inherit from a custom PathFollow3D
node called RailFollower
which adds extra logic to follow a path at a set speed.

Rail follower

Enemy code
The player ship doesn’t directly follow the path but rather is constrained to a 3D plane following the path; unfortunately, it gets a bit more complicated still. I learned that to look correct, the ship actually needs to pitch and yaw away from the camera as it reaches the extents of the screen. That caused problems for the aiming since I implemented the crosshairs as literal 3D objects attached to the front of the ship. Having the ship pitch/yaw as it moves caused the crosshairs to go off screen and required a lot of manual tuning to fix.

Player scene showing the crosshairs in front

Player and enemy paths
Rendering
Several people in the jam comments assumed I was using a shader to pixelate my game but the reality is much simpler. I just set the project’s window resolution to 256x224, enabled viewport scaling, and switched it to integer upscaling. The game is natively rendering in 256x224 and the pixel size just gets multiplied for larger windows.
This has the downside of causing the game to be very small by default; however, I used Itch.io’s canvas size option in the game settings to force the canvas to a larger initial size.
Time allocation
To help with my planning for future jams, I recorded my time throughout the jam:
Expand devlog
- Friday
- 11:00: Project setup
- 11:15: Ideation
- 12:15: Rendering
- 12:22: Rail follower / camera
- 13:20: Player movement
- 13:38: Targeting reticule
- 14:32: Bug fix
- 16:00: Hit box / health components
- 17:00: Laser components / spawn manager
- 18:40: Break
- 19:40: Basic enemy
- 20:20: Gameplay tweaks
- 23:20: Break
- Saturday
- 00:03: Scoring system
- 01:19: Power system
- 02:44: Break
- 03:16: Add turbo laser
- 04:30: Add boost
- 04:45: Enemy spawner
- 05:00: Trigger volumes
- 05:30: Fixing shader stutter
- 05:51: Game balance
- 06:00: Bookends
- 07:00: Break
- 07:40: Jam page
- 08:05: Break
- 12:38: Bookends
- 16:23: Beta testing
- 17:53: Transitions
- 18:35: Bug fixes
- 18:39: Game over screen
- 21:55: Level design
- Sunday
- 00:55: Break
- 01:39: SFX
- 02:55: Visual design
- 03:56: Break
- 04:20: HUD
- 05:49: Splash screens
- 06:43: Credits
- 08:17: Store page
- 10:00: Submission
- 10:14: Fix sound bug
- 10:17: Done
Expand time summary
Task Details Minutes Planning Ideation 60 Planning Total 60 Project Setup Godot setup 15 Project Setup Total 15 Core Code Rendering code 7 Core Code Shader preloader 21 Core Code Total 28 Mechanics Movement code 18 Mechanics Camera 58 Mechanics Crosshair 54 Mechanics Projectile system 100 Mechanics Hit box / health components 60 Mechanics Drone enemy 40 Mechanics Power system components 85 Mechanics Dodge 15 Mechanics Turbo laser 74 Mechanics Scoring system 79 Mechanics Enemy spawner 15 Mechanics Trigger volume component 30 Mechanics Total 628 Game Loop Bookends Level reset code 60 Game Loop Bookends Menu code 225 Game Loop Bookends Game over code 196 Game Loop Bookends Total 481 Level Design Level design 180 Level Design Total 180 Beta Testing Beta testing 93 Beta Testing Total 93 Bug Fixes Bug fixes 95 Bug Fixes Total 95 Balance Gameplay tweaks 180 Balance Score balancing 9 Balance Total 189 Audio SFX 76 Audio Total 76 Polish Scene transitions 42 Polish Visual polish 61 Polish HUD redesign 89 Polish Splash screens 54 Polish Credits screen 94 Polish Total 340 Jam Submission Itch page 128 Jam Submission Submission 14 Jam Submission Total 142 Break Break 514 Break Total 514 Total 2841 Dev Total 2327 (81% of allotted time)
I’ve heard from multiple devs that a short highly polished game will do better in jams than a longer less polished game so I spent most of my time working on polish rather than the game’s level. This unfortunately meant the final level was only 30 seconds long but I think it worked to prove out the concept.
Post-mortem
Results
Of the 717 final entries, I received 22 comments and won best itch.io page.
Given the jam isn’t ranked, I wasn’t expecting to win anything with over 700 other entrants so I was blown away that I won best itch.io page.
The most common feedback I received was that the visuals, polish, enjoyment, and genre choice were great but that the game was too short, hard to determine depth, and the ctrl keybinding was conflicting with browser shortcuts.
You can play Maximum Voltage on itch.io or check out one of my favorite submission to the jam:
Pros and cons
Pros
- Components made it easy to build levels and add new behaviors
- Kenney assets look great in low-resolution
- Focusing on core gameplay first was the right move
- High-score focus makes the game more enjoyable to replay
- My strength is cinematic events so a rail shooter really highlighted that
- Including hit% in the score screen made it more fun to replay
- Rapid fire is so satisfying
- Early web testing helped identify several critical performance, audio, and sprite issues
Cons
- Spent too much time working on the menus and didn’t have enough left to finish the first level
- Difficult to tell in editor what the bounds of the player’s movement are which made level design more trial and error
- There’s no reason in the final game to use the dodge so it just feels like a waste of power and by extension the single power pickups
- Developed the game with my speakers on low so I didn’t notice until after submission the master volume was way too high
- Should have made my game manager a general purpose scene transitioner as that would have reduced code in the main menu scene
- Ctrl was a bad key mapping - it’s hard to press and I learned from a reviewer that pressing Ctrl+W closes the entire browser
- No volume slider
- Several people had issues with depth perception
- Name didn’t quite match the game
- Should have used pictures instead of headers for the jam page, shouldn’t have repeated the title in the page text after the banner
- The aim-centering is bugged and re-centers the aim on the ship not the screen making it so your ship blocks the view when shooting anything straight ahead
What’s next
Due to popular demand, I started working on several updates to the game during the judging period. While I’d like to make a full rail shooter at some point, I don’t think Maximum Voltage has enough of an identity of its own for that but I am working to complete the first level of the game as I envisioned. This means adding enemies that shoot back and more cinematic encounters.
I have a lot of jams scheduled back-to-back this year so I won’t make any promises for the release date but know that it is in the works.

I failed Scream Jam 2024 | Negative
A recipe for disaster
After placing decently well in Scream Jam 2023, I was excited to push myself further in Scream Jam 2024. Since the last jam, I had been practicing my pixel art in daily challenges (1 2 3 4 5 6) and pushing myself to learn synthesizers. Going into the jam, I felt like I could do something more advanced than my 2023 entry and so I set myself two goals:
- Make a game that features more action
- Make all of the assets myself
But it wasn’t those goals which sunk me in the end though.
But why now?
I debated writing this post-mortem back in 2024 but I kept thinking I would eventually revisit the game so I didn’t want it spoiled. Half a year later, I’m ready to let this albatross go and talk about just where I went wrong.
The idea that never was
Story
Once the jam started, I initially decided on a game about a group of friends visiting a remote cabin in the dead of winter. As your character prepared to take a photo of the group with your instant film camera, invisible specters would cut power to the cabin and maim your friends. An errant shot from your camera would kill one specter and give you a way of defending yourself. As the cold set in, the player would discover they were locked inside by the specters and needing to quickly dispatch them before you froze.
Gameplay
As the specters would be invisible and require an exact shot from the camera to banish them, the gameplay would have centered around the player needing to find items around the cabin to help them reveal the specter’s positions. For example, I imagined breaking glass over a floor to reveal footprints where the specters were patrolling or overflowing a tub and watching for splashes on the floor. The player would have limited film so missed shots would not be an option if they wanted to survive.
The game would have been called Negative to reflect both the temperature the player was enduring as well as the film negatives integral to the gameplay.
Pivot
I really liked this idea and immediately set to work on a camera HUD and inventory system but quickly realized a glaring issue: art. While I had been practicing pixel art, I realized that I would need a lot of art to make an entire cabin not to mention all the items the player needed, animations, etc. I decided this was reason enough to pivot early and find a design that would be less taxing.
At that point, I feel like I was making the right decisions; however, it was my new idea that led to my demise.
The idea that shouldn’t have been
Story
My new idea was was still set in the remote cabin with invisible characters leaving footprints and a camera mechanic but with the twist that the player was really the monster and the footprints were being left by the cabin’s inhabitants. The whole idea being that the pale creature you play as feeds off humans by taking photos of them using a instant camera embedded in its head. To make it even more gruesome, the creature would hack up a polaroid of its victim’s last moments from its distended mouth after it’s finished digesting their consciousness.
Gameplay
Unlike the original idea, the humans would actively attack the player on sight so the gameplay would have pivoted to more of a stealth game with the creature needing to find ways to lure the humans around for better vantage points. The humans would have only been visible by their footprints to make the twist reveal less obvious at the end.
I really liked this new idea and became too attached to let it go despite it solving none of my existing issues while also creating new ones.
Art dilemma
Firstly, this new idea did nothing to address the art problem since I’d still needed a whole cabin’s worth of assets and things to draw the humans’ attention but now I also needed art for the monster twist reveal at the end.
Plot holes
Second, this new idea had tons of plot holes I couldn’t find a way to patch at the time:
- Why were the humans invisible if the creature literally has a camera for a head?
- Why don’t the humans just leave?
- How do I hide the fact that you’re a monster if you’re actively hunting things?
- And the list goes on…
Cursed game design problems
Finally, there’s a notion in game design of cursed problems: what happens when games which try to incorporate two or more mechanics that directly conflict. In my case, shifting the game to be more stealth focused fundamentally conflicted with the concept of needing to find your targets.
If the targets are invisible, how is the player supposed to avoid getting seen and attacked by them? Any visual queues for the targets would also give away their position making the trap laying mechanic useless. Similarly, if something is actively attacking you, you know where they are and can instantly photograph them.
I spent the entire rest of the jam trying to wrestle out a solution for this conundrum. I was convinced that similar games like Fatal Frame managed to make this work so I should be able to as well; however, having not actually played Fatal Frame at the time, I didn’t realize those games had wildly different mechanics from what I was trying to make despite the similar theming.
In hindsight, I can think of tons of ways to fix this both with story and gameplay but I was panicked at the time and hitting a mental block.
End of line
After several days had passed, I realized there was no way I could finish a game with the level of polish I wanted and just submitted my camera HUD proof-of-concept to the jam in defeat. A few kind folks left reviews saying they did like the concept and camera HUD but realistically, there was no game to be played.

This screenshot is about as interesting as the actual "gameplay"
Turning a negative into a positive
See what I did there? Sorry, anyways…
I’ve spent a good deal of time thinking about where I could have saved this jam and I believe I finally have a decent idea. I don’t think the failure was the story or even my cursed design problems. I suspect both of those were side effects of a mistake I made much earlier on.
I believe my failure was in deciding that I needed to grow my design skills by trying action-oriented gameplay but not accepting that story couldn’t be my main focus like it was in my 2023 jam entry. Because of the feedback I had gotten in my previous entry, I felt like story was my strong suit with my gameplay severely lacking. That’s why I set the goal to focus on gameplay which I think was the right move; however, I also wanted to embrace my strengths so I couldn’t let go of making story an important factor in the game.
To be clear, I don’t think it’s inherently wrong to want to play to your strengths while trying something new. Where I feel I went wrong was in trying to make both my top priority and refusing to let one be more important than the other. When I thought of something fun to play, I should have just followed it and made the story fit the gameplay rather than letting the story I already picked overrule the game. I’ve since participated in another jam (post coming soon) where I focussed exclusively on gameplay and was much happier with the results.
A message to those who fail
You will fail at a game jam. That’s not a threat; it’s a guarantee… and it’s not a bad thing.
Failing helps you understand where you still need to learn and it’s my opinion that the longer you go without failing, the harder that pill will be to swallow. So don’t be afraid to try new things and don’t let your failures go to waste. Learn from them by doing post-mortems (just preferably, don’t wait until 8 months after).
Negative is available to “play” on Itch; however, I’d recommend checking out the other amazing submissions to the jam instead.
I made a game for Scream Jam 2023 | Consignment
An old hobby
It’s been over a decade since I last made a game solo (made in Flash CS5 if that’s any indication) and I haven’t used a proper game engine in years but with all the recent talk about Godot, it finally felt like the right time to get back into game development.
I took a look at Godot 3 a few years ago; however, I just couldn’t bring myself to sit down and learn it. I’ve since learned one of the best sources for motivation is to hold yourself accountable to someone else’s timeline which is why this year I decided to enter into Scream Jam 2023 and force myself to finally learn Godot 4.
In this post, I’ll be walking through the design and development of my submission, Consignment, so I recommend playing the game first before reading on.
Content warning
Consignment includes themes of self-harm which will be discussed in this post.Story iterations
With only 7 days to learn the engine and make my game, I had to keep the scope small. From the get-go, I knew two things: I can’t make art to save my life and I don’t have the experience to make complex gameplay. From this, I figured my best bet was to make the game 2D and to center it around interacting with objects rather than fighting, platforming, or puzzle solving. For the setting, I drew inspiration from some of my favorite games: Dead Space, Prey 2017, SOMA, and the original System Shock and chose a derelict space ship.
I felt my gameplay wouldn’t be all that interesting so I wanted to make sure I had a good story to keep people playing. I wound up spending nearly all of the first day just brainstorming ideas.
The solo savior
My initial idea was to have the main character wake up from cyrosleep on a ship they didn’t recognize only to find the crew still frozen and the ship badly damaged. The intent was for the player to slowly learn how their cryopod had been transferred to this ship for delivery to a distant planet; however, an accident caused the ship to become damaged on the way. The damage prevented the actual crew from waking, leaving the computer with no choice but to wake up the main character instead. The player would have been tasked with repairing the cryopods to wake up the crew; however, they would have ultimately died in the process.
The ill-fated crew
The idea of a solo person sacrificing themselves to save the next seemed unique so I decided to explore that more. I changed the story to remove the passenger and focus only on the crew. To explain why only a single crew member could wake at a time, I had the idea that the ship could not re-freeze someone once revived and that it lacked the facilities to sustain thawed crew for the remainder of the trip. The ship’s computer would refuse to allow more than one person to be awake at a time since it was effectively a death sentence.
I wanted the game to have a strategy aspect so the story evolved to give each of them a different set of unique skills required to fix one or more systems of the ship. Some of these fixes would prove fatal to whoever performed them so players would have to learn which person was best suited for each task and in what order to do them. To further support the strategy angle, the player would be required to choose which character to wake next after each death.
I didn’t have time for a ton of content so I also wrote in a strict time limit to encourage trial-and-error replay. I had the idea that your ship had stopped in a faster-than-light shipping lane and would be obliterated by the next ship using the lane if you couldn’t move it in 5 minutes.
The realization
Four days into the jam, I couldn’t shake the nagging feeling that what I had written was less horror and more sci-fi drama. I was also growing concerned that the gameplay would be too frustrating for players as I don’t have the best track record for strategic design. Furthermore, I felt having a time limit would make the game feel less like horror and more like action. It wasn’t an easy decision, but I made the choice to massively scope-down the game and refocus on purely atmospheric horror from the perspective of a single character with an emphasis on feeling helpless.
I kept the lore aspects of the previous story but rewrote it to only play as the captain. The captain, Alicia, would awake to find the ship nearly destroyed and the chief engineer missing. Through computer terminals and announcements from the ship’s AI, Sentinel, the player would learn the ship’s cargo includes over 7000 people in cryostasis including the engineer’s daughter. The player would learn how the chief engineer was woken first to repair the ship’s reactor only to find that they could not navigate the ship out of the shipping lane as the bridge could only be accessed by the captain. The player would eventually find how the engineer had taken their own life to force the ship to wake the captain to finish the task.
With that knowledge, the player would then be required to navigate the ship out of the lane before it was too late; however, they would find the ship’s engines could not be started without rerouting yet more power from other systems. The player would be forced to turn off the ships’ radiation shields to start the engines and in doing so would bathe the crew and its cargo in a lethal dose of radiation. Rerouting the power would allow the ship to move clear thus preventing any future ships from meeting the same fate; however, the ship’s reactor would fail in the process leaving no hope for the souls aboard.
This became the final story for the game and was the inspiration for its name: Consignment.

The game's thumbnail featuring the remaining 3 crew members
Development
Art direction
I can’t art to save my life so I spent a good chunk of the first day just looking for free tilesets I could use. I found some really nice sets but none of them quite felt right to me. Every top-down asset pack I found had cartoonish characters which just didn’t fit the direction I was going for. Eventually, I resolved myself for what needed to be done and opened Aseprite to draw my own.
Shading and color choice have always been a problem for me so I wanted to start with as small a palette as possible. Scrolling through the default selections in Aseprite, the CGA high intensity option caught my attention. I felt the expectation for games made using the CGA palette would be much lower than ones using something like the NES or Atari 2600 palettes. I also liked the novelty of using CGA’s magenta for blood effects.

Fun fact: For most of the jam, the player character was just this sad little square because I was dreading having to draw a person
I still didn’t have time to draw a ton of tiles so I chose a top-down perspective that only shows the faces of north walls.

In Consignment, only north wall faces are visible

Games like the Legend of Zelda show all wall faces
Photo: https://www.zeldadungeon.net/
Audio
I don’t know much about audio and didn’t have time to record my own samples anyways so for the game’s sound effects, I used the FilmCow Royalty Free Sound Effects library. This library turned out to be the perfect fit as it had a ton of great ambient sounds as well as scifi effects.
I’ve always loved the computer voice lines from Prey 2017, such as those from Morgan’s Suit, so I wanted to give Sentinel a similar voice. I followed a tutorial for creating robot voices which got me pretty close but I wound up tweaking the steps a bit. For the final mix, each line was comprised of two tracks each with a copy of my voice but with different effects applied:
- For track 1:
- Increase pitch 10%
- Add echo with a delay time of 0.02 and decay factor of 0.6
- Decrease pitch 20%
- Decrease pitch 20% again (adjusting once by more didn’t get the same effect as doing it twice)
- For track 2:
- Reduce tempo 2%
- Add echo with a delay time of 0.01 and decay factor of 0.6
Something I found while mixing the audio was I needed to break lines up into shorter phrases. Applying a tempo adjustment to longer lines would cause the tracks to desync so much that you couldn’t make out what was being said. It also sounded odd during playtesting to have voice lines start with no introduction so I added a couple beep sounds from FilmCow’s library to the start of each line and adjusted their pitch to create an announcement chime.
Architecture
For being such a short game, Consignment has more structure than you might expect. The game is divided into two core scenes: main and ship. The main scene primarily handles switching screens, loading the ship scene, and spawning the player. Meanwhile, the ship scene is responsible for tracking game state. Nothing particularly noteworthy here; however, it’s the structure of the ship scene that I really want to discuss.
The ship scene is built very literally with it being comprised of several smaller scenes each representing one of the main locations from the game: the cryo room, the bridge, and engineering storage. Each of these room scenes has its own tilemap, audio queues, trigger volumes, and scripts. The ship scene itself only actually contains the hallway tilemaps and the logic to relay signals between the rooms.

The tilemap, doors, and props in the ship scene are just for the connecting hallways
The idea was to make each room fully self-contained in code and layout. The rooms know nothing of each other nor do they know how the ship scene works. They just emit signals when something significant happens and expose public methods to change their state (if applicable). Picking up the override codes from engineering storage is a good example of this segregation of duties:

Here you can see the "signal up, call down" methodology the architecture is based around
Aside from keeping game logic separated, this approach also made it easy to adjust the ship’s layout. Just drag a room somewhere, update the hallway tilemap, and I’m done. This made development a breeze since I could quickly test with rooms close together.

All of the rooms were next to each other for most of development
There are many different ways to structure a game with no one approach being right for every situation but this is certainly one I’ll remember for the future.
Reception
Of the 497 entries, Consignment placed:
- #13 in Story
- #22 in Sound Design
- #42 in Enjoyment
- #75 in Horror
- #83 in Aesthetics
And WOW! I’m honestly shocked by how well it did and super thankful to everyone who took the time to play and give feedback.
I didn’t expect rankings anywhere near this high but I have to admit enjoyment is the most surprising. Given my gameplay loop boils down to just pressing ‘E’ a few times, I expected to score much lower than I did. While games like SOMA and Amnesia also heavily rely on so-called fetch quests, they have additional mechanics to keep the game interesting along the way like stealth. I suspect that had Consignment been longer, I would have scored much lower but as-is I think the short duration helps keep the game from feeling too stale.
Aside from enjoyment, I was also surprised just how many people commented about liking the art direction. It was especially cool to see people mention it taking them back to their DOS gaming days. I may just revisit this palette again in the future because of that.
If you haven’t already, I highly recommend checking out the other great games submitted to this year’s Scream Jam. Some of my favorites are:
Retrospective
The ending
My intent was for the horror to come from the player’s realization of being in an unwinnable situation with others depending on them to do something about it. I wanted players to experience the dread and regret of letting someone down and to punctuate it with a feeling of isolation and lack of control. Unfortunately, I’m not sure those themes came across how I intended.
By far, the most common feedback I received was from players not sure if they had “failed” the game or not. It’s one thing if a player feels conflicted about what they did but it’s a whole other problem when they aren’t sure if they completed the game. Not knowing could have left some players believing there were other “better” endings they just didn’t find which takes away from the theme. In retrospect, I can definitely see a few reasons why players were led to think this way.
For starters, the power-rerouting segment at the end looks too much like it has multiple solutions. In reality, no combination of systems can supply enough power to restart the engines without also shutting down the radiation shields. I tried to make this obvious by showing how much power was required and how much was available on the main computer; however, I don’t think this was clear enough and I suspect most players didn’t even know the main computer would tell them that. This would have been much clearer if the rerouting took place through an interactive menu with a real-time power readout and switches to let them experiment.

The result of re-routing power from every system except the shields
Furthermore, I don’t think the impact of turning off the radiation shields was very clear. I got the impression some players thought at least some of the crew/passengers survived. In hindsight, I had to lookup what a lethal dose of radiation was while writing so I shouldn’t have expected players to know just how deadly 8,000msv is. I tried to make this clear with the final message indicating “multiple cryotube failures” in the cargo hold but I don’t think it was enough. Forcing the player to reroute power from something more directly impactful like cryo storage may have been a better option. Alternatively, showing the immediate signs of radiation sickness on the player and other cryotubes may have also helped.
On a related note, I’m not certain I made it clear enough the ship was beyond hope of rescue by the end. Through the bridge computers, I was trying to convey how the ship had lost its communications array, most of its lights/beacons, only had a few days of oxygen left, and was 20 years away from anyone who could help it. Additionally, the ending sequence was meant to imply the ship’s reactor had melted-down and taken the hydraulics with it causing total power loss and sealed doors. Despite all this, I don’t think I did enough to build the world outside the ship to make it clear why nobody would be able to help.

The final moments of the game before the credits were meant to let the player reflect on just how final the ending is
Audio design
Some great feedback I got on the submission was to look into applying ring modulation to the voice to make it sound more robotic. Audacity didn’t appear to have a ring modulation effect built-in but I found a plugin for it online. It’ll take some time to learn how best to use it but I definitely like the effect it creates.
Code
Changing the game’s premise after I already started development left the final build with quite a bit of dead code for handling the character transitions. In fact, there is even an entire character select menu and death system built in that just never gets activated. Despite that, the code was actually pretty clean up until the last two days of the jam.
Then all hell broke loose.
The main problem is with the segregation of duties between the ship and bridge scenes. See, the ship’s script is what triggers all the random ambient sounds and screen shaking effects while the bridge is what animates the ending sequence. This sounded fine when I first designed them except I forgot two things: 1) the ship needs to stop playing random sounds when the ending starts and 2) the ending animation requires screen shaking. I didn’t have time to refactor the scenes so the ship and bridge wound up coupled by a complex sequence of signals the bridge emits to request different sound and screen shake effects from the ship.
Actually, the ending sequence is even more rough than that. The sequence isn’t made using Godot’s AnimationPlayer like you might expect. It’s actually built from a ton of sequential timers. I knew Godot had an animation player; however, I didn’t know it could control scripts and I didn’t think I had enough time to learn about it anyways. Now that I’ve had a moment to read about it, I know it would have worked much better than what I did.

These are just a few of the callback functions for all the ending timers
Wrap up
Overall, this turned out to be a great way to finally learn Godot and get back into making games again. Even after the jam, I’ve been tinkering with small projects in Godot and wanting to learn more. I’m already excited for my next jam and looking to enter another this winter.
All that said, I haven’t been sleeping on my other projects either. I’ve been working to learn FreeCAD over the past few weeks with the intent of shifting my half-scale pinball machine development over to it.