DEV Community

Cover image for I stopped letting the LLM write GDScript. Now one sentence becomes a playable Godot game in ~25 seconds
Lượng Lê
Lượng Lê

Posted on

I stopped letting the LLM write GDScript. Now one sentence becomes a playable Godot game in ~25 seconds

I'm an AI engineer, not a game developer. A few weeks ago I wanted to know: how fast can an AI agent go from "a ninja platformer where you collect stars" to something I'd actually want to play?

The usual answer is "let the LLM write the code". I tried that. It's slow, it burns tokens, and Godot 3/4 API mix-ups break the build all the time. Even when it compiles, the game feels flat: no coyote time, no screen shake, and hitboxes that don't match the sprites.

This is fine: my LLM wrote 800 lines of GDScript, Godot 3 code in Godot 4

So I built Spawn Point around a different idea:

The LLM shouldn't write game code. It should design the game, and a compiler should build it.

Pixel Arena, a generated top-down shooter

What it looks like

pip install spawnpoint-studio
spawnpoint llm up      # local model, ~11 GB VRAM (or any OpenAI-compatible API)
spawnpoint create "a ninja platformer where you collect stars"
Enter fullscreen mode Exit fullscreen mode
Design:
  "Ninja Star Dash": platformer, palette candy, goal collect_all, short, difficulty 2
  player: double_jump, stomp; jump 4.0 tiles; speed fast; feel floaty
  enemies: 4x Goblin (walker), 2x Spider (hopper); pickups: 10x Star; hazards: spikes
  [L0 core loop] ok in 5.5s
  ▶ playing at http://localhost:8060/
  [L1 goals & enemies] ok in 5.1s
  [L2 feel & polish] ok in 5.1s
Done in 25.7s (LLM 2 call(s), 977 prompt + 256 completion tokens).
Enter fullscreen mode Exit fullscreen mode

The browser opens as soon as the first layer is playable and reloads as the next layers land. The whole game takes two LLM calls and about 1.2k tokens.

Then you iterate in plain language:

spawnpoint tweak out/ninja-star-dash "jump 20% higher and add a dash, night colors"
#   palette: "candy" -> "night"
#   player.abilities: [...] -> ["double_jump", "stomp", "dash"]
#   player.jump_tiles: 4.0 -> 4.8
Enter fullscreen mode Exit fullscreen mode

Only what you asked for changes. The level layout stays the same.

How it works: LEGO, not prose

Drake meme: no to the LLM writing 800 lines of GDScript, yes to the LLM filling a JSON form while a compiler builds the game

Instead of generating hundreds of lines of GDScript, the pipeline looks like this:

  1. Design. The LLM fills a small, enumerated GameBrief (genre, abilities, enemy archetypes, pickups, goal, feel) using guided JSON decoding, so even a 7B model can't produce malformed output.
  2. Assemble. Deterministic code turns the brief into a game graph: pre-tested Godot components, an ASCII level map and declarative rules. Levels are re-seeded until the compiler can prove that everything is reachable.
  3. Compile. A Python compiler validates the graph in about 1 ms, with error messages written for an LLM to fix. Then Godot runs headless and builds the scenes itself, and a smoke test plays the game for a second before you ever see it.
Typical "LLM writes code" agents Spawn Point
How code is produced GDScript from scratch Pre-tested components + JSON graph
Time to a playable build minutes to hours seconds
Game feel none by default coyote time, jump buffer, squash & stretch, hit-stop, screen shake, particles, SFX
Hitboxes drift from the visuals traced from the sprite's pixels
Failure mode crashes, syntax errors structured diagnostics before Godot runs

Things I didn't expect to build

Bots that playtest your game and fix it. Three bot skill levels (novice, average, expert) press real keys and navigate with a jump-aware path planner. Then a bounded tuner adjusts the game:

before:  novice  won 1/3  deaths 5  (Spikes 4, Frog 1)
round 1: Player.Hurtbox.size_scale = 0.75   (Spikes caused 6/7 deaths)
         Player.Health.max_health = 4       (novice bots won only 1/3)
after:   average won 2/3
Enter fullscreen mode Exit fullscreen mode

Right-click to edit. spawnpoint studio opens a local web cockpit with the game running in the middle. Right-click an enemy inside the game and type "double its health and make it shoot fireballs". The model returns a patch scoped to that entity, the compiler checks it, and the game reloads.

Pixel art with matching collisions. Sprites are generated procedurally, imported from your own sheets, or drawn by an image model through a plug-in (A1111 / any OpenAI-compatible images API). Collision polygons are traced from the pixels, so hitboxes always match what you see.

The model: SpawnPoint-Coder-7B

I wanted the whole studio to run offline, for free, on a consumer GPU. So I fine-tuned a 7B model (QLoRA, then AWQ 4-bit) just for these tasks: designing briefs, applying tweaks and editing entities. The compiler doubles as the data filter and the judge: every training example has to compile.

On 30 game ideas written by hand (English and Vietnamese, 153 checks):

v1 v2
Prompts fully right 73% 87%
Checks passed 94% 97%
Held-out briefs (exact match) 36% 88%
Vietnamese → English 52% 97%

It's on Hugging Face: smoky1496/SpawnPoint-Coder-7B-AWQ. Claude, OpenAI or any OpenAI-compatible API work too.

Honest limits: it's tuned for 2D platformers and 2D top-down games. Ask for a 3D RPG and you'll get nothing special. The GDScript comes from the tested component library, not from the model.

Try it

No GPU? spawnpoint examples copy pixel_hopper && spawnpoint build pixel_hopper.json --run builds an example game without any LLM.

I'd love feedback, especially from people who actually make games: what's the first game you'd type in? Drop it in the comments and I'll post what comes out.

Top comments (0)