Background image 1Background image 2Background image 3Background image 4Background image 5
Beyond 'It Works': A Deep Dive into Game Jam Architecture
September 4, 20258 min read

Beyond "It Works": A Deep Dive into Game Jam Architecture

The Countdown Begins

The timer starts. 48 hours. That seems like a lot of time, but when you have a goal at the end, it turns into a frantic sprint. The theme is announced: "Your cure is your curse." My mind draws a blank. Tick... tock... A mix of excitement and a little bit of panic takes over.

Every game jam begins this way for me. It’s a mad dash from a single idea to a playable thing. But amidst the chaos, there’s a method. Over several jams, I’ve developed a personal playbook for turning that panic into a product. In this post, I’m going to pull back the curtain on my process, focusing on the backbone of it all: the code, the structure, and the composition that holds the game together.


My Golden Rule: Scope, Scope, and Scope It Down Again

Before I write a single line of code, I have to talk about the most critical skill in a game jam: managing scope.

You're not going to complete your entry if you try to recreate World of Warcraft. Your idea must be small enough to be completed and polished in about 60% of the allotted time. The other 40% will be devoured by bugs, unforeseen problems (like exporting builds—web builds take a really long time, apparently), and the desperate need for sleep. Every technical decision I make is guided by this principle.


The "Just Make it Work!" Counter-Argument

This summer, I started doing game jams with my friends. The goal was simple: actually finish and release small games. I've now managed to release two (Broberry and Parasitic God) and, in the process, I've found my own development rhythm. My mindset is always to keep the code as clean and maintainable as possible, even under pressure.

This approach isn't always popular.

When I talk to my friends, they often say, "Proper architecture takes too much time! Players don't care about code; they care about the game." They have a point. A beautiful codebase is worthless if you don't have a game to show for it.

But here’s my counter-argument: good architecture doesn't slow you down; it speeds you up. A clean, modular structure isn't a chore. It's a powerful tool that allows you to iterate, debug, and add features faster than you could with messy "spaghetti code."

Let me show you how.


My Process: From Theme to Systems

When the theme drops, I spend a few minutes thinking about what kind of game I want to create. Once I have a rough idea, I immediately start thinking about the systems. What modular pieces will I need? Can I build a weapon system where I can easily create a sword that deals poison damage or a gun that shoots healing bullets?

Thinking in terms of systems and reusable parts is the key. This naturally leads to my favorite design pattern for game development.

My Secret Weapon: Building with LEGOs (Composition)

In programming, there's a principle: "prefer composition over inheritance." In a game jam, I treat this as law. For those who aren't familiar with the terms, here's a quick breakdown.

The Inheritance Trap

Inheritance is what we're often taught first. It's an "is-a" relationship. A Cat is an Animal. A Dog is an Animal. This creates a rigid family tree.

// The "is-a" relationship
public class Dog : Animal { ... }

This works for simple things, but it falls apart with complex game mechanics. Let's use a weapon example. You might start with this:

public class Weapon { ... }
public class MeleeWeapon : Weapon { ... }
public class RangedWeapon : Weapon { ... }

Easy, right? But now you want a sword that also shoots projectiles. Uh oh. Does it inherit from MeleeWeapon or RangedWeapon? What if you want a gun that sets enemies on fire? Do you make a FieryRangedWeapon class? What about a healing, fiery, projectile-shooting sword?

You end up in a tangled mess of classes. This is the inheritance trap, and it's a nightmare under a 48-hour time limit.

The Composition Solution: Think LEGOs

Composition is a "has-a" relationship. Instead of saying an object is something, you say it has functionalities.

Think of a GameObject in Unity or a Node in Godot as a single LEGO brick. On its own, it does nothing. The magic happens when you start snapping other bricks—components—onto it. A "weapon" in my game isn't a complex class; it's an empty object that has a collection of scripts defining its behavior.

Let's rebuild our crazy weapon idea with composition:

  • We create small, single-purpose scripts (our LEGOs):
    • DealDamageOnHit.cs: Has a damage value.
    • SwingAttack.cs: Has a swing animation.
    • ShootProjectile.cs: Has a bullet prefab.
    • ApplyFireEffect.cs: Has a burn duration.

Now, we can build any weapon just by mixing and matching:

  • Simple Sword: GameObject + DealDamageOnHit.cs + SwingAttack.cs
  • Flamethrower: GameObject + DealDamageOnHit.cs + ShootProjectile.cs + ApplyFireEffect.cs

Suddenly, you're not writing new classes; you're just assembling new objects. It’s fast, flexible, and exactly what you need when the clock is ticking.


The Payoff: Modding Support for Free

So, what’s the ultimate benefit of this LEGO-based approach? You get powerful features that seem impossible in a 48-hour jam. For my game Parasitic God, this architecture meant I could implement a full-blown modding system with very little extra effort.

It wasn't a feature I planned for. It was a natural, almost free, consequence of the data-driven design I had already built.

The Core Idea: Game Content is Just Data

The central principle is that the "things" in my game—miracles, events, and upgrades—are not hardcoded. They're defined in simple JSON text files.

The C# code is just an engine that reads and interprets that data. My GameLogic.cs doesn’t know what a "Miracle of Growth" is; it only knows how to process a list of abstract Effect resources. This separation is what unlocks modding.

It’s built on three pillars:

Pillar 1: JSON as the Blueprint

Instead of coding a miracle's properties, I define its structure in a "Data Transfer Object" (DTO) like MiracleDto.cs. This means anyone can define a new miracle in a simple .json file—no compiler needed.

{
  "Name": "Gift of Life",
  "FaithCost": 25.0,
  "Effects": [
    {
      "Type": "AddResource",
      "TargetResource": "Followers",
      "Value": 50.0
    }
  ]
}

Pillar 2: The Universal Loader

The game's MiracleLoader.cs finds and loads these JSON files. The trick is that it looks in two places: the game's internal res:// directory for my default files and the player's special user:// data folder for mods. The loader code simply loads the defaults and then loads the user's mods, allowing players to add new content or overwrite existing files.

// From Core/MiracleLoader.cs
public static Dictionary<string, MiracleDefinition> LoadAllMiracles()
{
    var loadedMiracles = new Dictionary<string, MiracleDefinition>();
    
    // 1. Load the default game content
    LoadMiraclesFromPath("res://Mods/Miracles", loadedMiracles);
    
    // 2. Load the user's mods, overwriting defaults if names match
    LoadMiraclesFromPath("user://Mods/Miracles", loadedMiracles);

    return loadedMiracles;
}

Pillar 3: The Reusable LEGOs (Effect System)

This is where it all ties back to composition. How can a JSON file actually do things? The "Effects" array in the JSON is a list of commands. Each command tells my C# engine which LEGO brick to use. The MiracleLoader.cs reads the "Type" string (e.g., "AddResource") and creates an instance of the corresponding C# Effect class.

A modder can create a complex new miracle—modifying stats, applying buffs, and unlocking other content—all without writing a single line of C# code. They just assemble the available Effect LEGOs in a JSON file.


The Final Result & What's Next

This system is the ultimate proof that good architecture pays for itself. The time I spent separating data from logic wasn’t a detour; it was a direct path to a more robust, flexible, and feature-rich game.

So when my friends say, “Just make it work,” I say, “Let’s make it work right.” Because sometimes, working right from the beginning means you get incredible features like a modding system, not as a massive time sink, but as a happy accident.

Going forward, I'm definitely going to take part in more game jams. While I'm happy with my coding practices, I've realized I need to grow as a game designer. My games work, but they often lack that certain oomph. That's the crucial skill I need to develop to create better experiences for players.

In a perfect world, I'd find a team where I could focus on what I love: coding and creating tools for designers to bring their visions to life.


References