← Games

GearTopia

A Factorio-like factory sim with Dwarf-Fortress depth levels and no electricity — water wheels, shafts and gears, dug downward while goblins climb up the tunnels you dug.

Role
Solo — design, engineering, art direction & marketing
Year
2026
Stack
Godot · C# · GDScript · Simulation · Data-driven architecture · Steam launch prep
TL;DR

A factory-building game in Godot (C# + GDScript), in active development with a live Steam page: dig down through Dwarf-Fortress-style depth levels and power the whole factory mechanically — shafts, gears and gear ratios instead of electricity. Custom simulations underneath it: RPM/torque networks across Z-levels, flowing multi-liquid water, goblin raids and turrets, all driven by data files, with the hot loops written in C# for the frame budget. My most technically ambitious project, and the one I'm shipping — the Steam page is up and a demo is next.

What it is

A Factorio-style factory builder with two deliberate twists. First, the world has depth levels in the spirit of Dwarf Fortress — you dig downward and build across multiple Z-layers, and flat ground on the surface runs out fast enough that going down isn’t optional. Second, there’s no electricity: the whole factory runs on mechanical power — water wheels, shafts and gears — so power routing is a physical, spatial puzzle rather than a wire you drop anywhere.

On top of that sits the reason to build: dwarven fortresses under siege order iron from you, and they hold exactly as long as you keep shipping. And up the same tunnels you dug for logistics, the goblins come to you.

Where it is now

In active development, solo, since July 2026 — currently at internal revision 31. The Steam page has been live since August 2026, the trailer is shot, and the game runs as a complete vertical slice: a goal, a threat, a full production chain, saves, settings, two languages, music and sound. What’s left before the public demo is a tutorial, a playtest round, and an art and readability pass — not systems.

I also do the marketing myself: store text, trailer, Reddit posts and YouTube devlogs. The first week after the page went up produced about forty comments of real feedback, and that feedback rewrote the plan — including adding the fortress system below, because the page’s central promise wasn’t yet backed by the game.

The core system: mechanical power

Power is simulated as networks of connected shafts, gears, and machines:

  • Energy sources (water wheel, windmill, steam engine) produce an RPM and a torque.
  • Gears change RPM by their tooth ratio — rpm_out = rpm_in × (teeth_in / teeth_out) — so gearing up for speed costs you torque, and vice-versa.
  • Machines only run when the network delivers their required RPM (within a tolerance) and enough torque.
  • Shafts cap how much power they can carry, so overbuilt lines break.
  • Networks resolve to states like RUNNING, OVERLOADED, or CONFLICTED — the last when two sources fight over the same network at different RPMs.
No electricity — everything runs on mechanical power

  source ──shaft──▶ gear ──shaft──▶ machine
   rpm, torque    teeth ratio    needs target rpm ± tol + torque
                rpm_out = rpm_in × (teeth_in / teeth_out)

  networks solved with BFS, rebuilt lazily only on change:
    RUNNING · OVERLOADED · CONFLICTED · IDLE · SHAFT-BROKEN

  60 Hz deterministic tick ▸ Mechanical ▸ Machines ▸ Conveyors ▸ Fluids

The network solver runs a BFS over the grid and rebuilds lazily — only the dirty parts, only when something changes — rather than recomputing every tick. Deliberately, a network has just two outcomes: capacity covers demand, or it doesn’t. One drill too many doesn’t slow the line down, it stops the whole shaft — the furnace, the crusher, the belt and the other five drills — which is the decision the game is actually about.

The war you supply but never fight

The newest system, and the one carrying the game’s positioning. A line of named dwarven fortresses stands between the goblins and you, each with its own readiness, wall, and appetite for a particular category of goods. Every raid is resolved against that line first, and whatever the fortresses can’t absorb leaks through to your factory. Ship them iron and they hold; ignore one and it stops writing to you — not “reputation −5”, just a name that goes quiet.

Two behaviours fell out of the model rather than being designed in: the line switches on front-to-back as your factory grows, so early waves are one fortress’s problem and you supply one rather than five; and load shifts backward when a fortress runs out of readiness, not when it falls — so its neighbour starts paying three waves before anything visibly breaks. Both were found by running the line through console commands on a bench, not by reading the code.

The rest of the factory

  • Depth & cross-level transfer. A multi-Z-level world you dig through; shafts and conveyor lifts carry both power and items vertically between levels, and you can peek at the layer below through the holes you made yourself.
  • Data-driven content. A building is just a .tres config (footprint, ports, gear/machine/shaft/conveyor stats, optional behavior script) auto-loaded from a folder; items, recipes, ores, liquids, enemies, raid profiles, research nodes and world-generation profiles work the same way — currently 27 buildings, 40 items, 38 recipes. Adding content is a data change, not code.
  • Fluids that don’t respect ownership. A multi-liquid cellular solver: water spreads, pours from floor to floor, floods buildings, and drowns whatever is standing in it — goblins included. Pumps, pipes, tanks and sluices exist to make it go where you decided instead.
  • Threat & defence. Goblin raids sized against your own production rate, pathing through the tunnels you dug via a flow field, met by turrets with line-of-sight firing arcs and ammunition as its own class of resource.
  • Progression. Procedurally generated orders from named fortresses (with authored text in two languages), an economy where gold is only ever earned rather than mined, and a research tree that unlocks locked recipes.
  • Everything besides systems that a game needs. Menu shell and settings, versioned saves (an incompatible slot refuses to load rather than loading wrong), full RU/EN localization, music and sound, a 50-command dev console, and my own capture tools — a timelapse recorder and a scripted trailer camera.

Performance, and the C# decision

Performance was a first-class goal, and it drove a real architecture call. Profiling pushed me to move the heavy simulation into C# — the spatial grid, the mechanical, machine, conveyor, turret, fluid and lighting systems, runtime building state, and zero-GC item queues — while keeping the lighter, iteration-heavy systems in GDScript (UI, player, rendering, building behaviors). In practice that meant porting core systems across languages mid-project — a deliberate trade of short-term rework for the frame budget a factory sim needs when the map fills up.

The sharper lesson wasn’t the port itself but the boundary. Crossing from GDScript into C# isn’t “slightly slower”, it’s garbage: one check-then-read against a shared dictionary costs roughly 200 bytes, and on a large factory that turned into visible GC pauses. The rule that came out of it — hot state lives in a field on the object, the dictionary is only the save format, and anything called every tick lives in C# rather than in a GDScript behavior — was worth more than any single optimization.

Two other measurements paid off disproportionately. Save files were bloating not from the amount of data but from its shape: a 64×64 floor map took 33 KB to hold 512 bytes of information, because booleans serialize to 8 bytes each. Compression took a save from 1.19 MB to 30 KB — 39.8× — and kept old saves readable, where bit-packing would have gained about the same and killed every existing world. And a lag spike in manual crafting turned out not to be in the UI at all: it was a “how many of these can I craft” check that was linear in the stack size.

Why it’s here

It’s my clearest example of systems engineering at scale — a custom simulation of mechanical power across a multi-level grid, a fluid solver, enemy AI, and a data-driven content pipeline that makes new machines trivial to add — plus pragmatic performance work, including a cross-language port, done because the game genuinely needed it. It’s also the project where I do everything else a solo release takes: design, art direction, store page, trailer and community. And most of the expensive bugs in it were caught by measuring rather than by reasoning, which is the habit I’d bring anywhere.