Zero Handwritten Lines: Claude Code Built This Godot Tower Defense in 5 Days
Vibe coding a small game · Kickoff: 5 days, 8,400 lines of code, no line handwritten, and getting the AI to check its own work first
The image above shows what the game looks like now. It's called "Holy Light Defense", a vertical tower defense, started on October 25 — that's day 5:
- Two game modes: Campaign mode procedurally generates levels from stage 4 onward, endlessly playable; versus mode is 1v1 — recruit units, drag them into slots, merge to upgrade, merge to hero.
- All assets self-made: 22 characters plus all scenes and UI generated by AI, 21 sound effects and background music synthesized from code.
- Playable on mobile: Packaged as a 13.84MB WeChat mini game, already running on an iPhone inside WeChat, adapted for the Dynamic Island.
- Code scale: 77 GDScript files, 8,408 lines, plus 573 test functions.
All that code was written by Claude Code. I did not handwrite a single line. What I did was specify requirements, playtest, make the call, and handle things like account registration and QR code login that can only be done by a person.
This series records the entire process chronologically from kickoff to release: kickoff, gameplay, assets, packaging, WeChat mini game, versus mode, Douyin and software copyright, release. It has not been released yet; later posts will follow the progress.
This post covers day one — kickoff. Three things deserve their own discussion: what the AI asked before starting, which platform constraints it found after the engine was locked in, and why it built a toolset for the AI to inspect its own work before writing the first line of gameplay code. The ability to keep adding features over the next 5 days rests on that toolset.
The first words of kickoff: the AI asked 4 questions first
My first sentence to Claude Code was: make a tower defense game, use Godot, and reference an old game for the characters.
It did not start writing. It raised a copyright question first: the character names and art of that game belong to the original publisher. If the plan is a public release, only the gameplay and theme can be borrowed; the names, art, and data are unusable. Then it pinned down the scope with four multiple-choice questions:
| Question | My choice |
|---|---|
| How will the output be used? | Public release |
| How to handle art assets? | AI-generated original assets |
| What form of tower defense? | Path tower defense (enemies follow a fixed path, player builds along the roadside) |
| How big is the first playable version? | Minimal playable: 1 map, 3 tower types, 8 waves of undead, gold and hit points |
These four questions seem ordinary, but each one mattered later. "Public release" meant copyright rules were written into the project notes from day one: no existing game names may appear in the code, data, art, or image generation prompts. "Minimal playable" meant a fully completable match existed by the end of day one, and every later change built on top of that match.
I chose Godot; the AI uncovered platform constraints
I specified the engine outright without cross-comparison. The AI didn't challenge the choice; instead, after I named the target platforms — Steam, WeChat mini game, and Douyin mini game — it checked Godot's situation on each platform. Findings:
- Douyin has an official Godot SDK, but it supports only Godot 4.5, does not support custom export templates, and runs single-threaded. The project uses 4.7.
- WeChat has no official Godot support — only community-maintained export templates, one of which has a 4.7 version.
- Package size: main package cap is 4MB, total package cap 20MB (initial research found 30MB; a later preview rejection revealed it's 20MB). Godot alone takes several megabytes (measured 8.4MB compressed), so it must go into a subpackage.
- iOS requires enabling WeChat's high-performance mode.
- No system fonts exist in mini-game environments — Chinese fonts have to be bundled.
The AI's recommendation: keep Godot, build the Steam version as planned, and after finishing the three maps, spend a day or two exporting to real devices for verification — if verification fails, consider switching engines. Later events proved this necessary: real devices got stuck loading, iPhones showed black screens — these problems only surfaced at this stage, covered in detail in part 5.
On day two, another global decision was made: unified vertical orientation across platforms, even on PC a tall narrow window. The resolution changed from 1280×720 to 720×1280; all three maps were rearranged for vertical; the top-right reserved space for the WeChat mini game capsule button. The later this decision comes, the more rework.
Build tools first, so the AI can check its own work
Using AI to write games has a natural blind spot: it cannot see the screen and never plays the game by hand. Code compiling does not mean the game is playable; tests all passing does not mean the screen has no misalignment. So on day one, before writing gameplay, a toolset for the AI to verify itself was built — all as make commands:
| Command | What it does | Problem it blocks |
|---|---|---|
| make test | Runs all unit tests (GUT framework), headless, non-zero exit on failure | Changing one thing breaks another |
| make lint | Treats GDScript warnings as errors | Godot's CLI doesn't print warnings by default, problems silently linger |
| make smoke | Headless game start, auto-completes a level at 8x speed, fails on any engine or script error | Runtime errors unit tests don't catch |
| make frames | Auto-plays a level, saves one PNG per game second | The AI can't see the screen |
The first three follow standard practice, but each has Godot-specific traps. For instance, Godot's CLI never prints GDScript warnings. Without special handling, warnings never appear in the output the AI can see. make lint works by temporarily adding a config file that escalates all warnings to errors, then deleting it after the run.
For testing, a project rule requires writing tests before writing implementation. Test count went from 118 on day one to the current 573. The AI honestly stated a limitation: GDScript has no coverage tooling, so the "80% coverage" requirement cannot be measured — the test-first habit is the only guarantee.
make frames: letting the AI see the game screen
The fourth command is the most critical of the set. Godot's built-in recording feature can output the game frame by frame as images. make frames runs the game auto-playing the first level at 4x speed for 90 seconds, saving one PNG per game second — 91 images total. The AI uses its image-reading capability to go through them, checking whether characters stand on the path, health bars are occluded, and effects sit in the right positions. The project notes put it plainly: this is the only way to see the game in a command line.
Over the next five days, it was used every time the UI or art changed. When switching to vertical, the AI used the same approach to batch-capture several aspect ratios of the interface and check each image for buttons and menus out of bounds.
The toolset had its own failures; the AI tripped over it too. Once, it redirected make smoke's output to the same file it was about to read next — reading a file that grows while it reads leads to an infinite loop. Another time, more serious: it made a startup optimization that passed verification in the editor, but once exported to an installation package, an array was cleared by the engine and clicking "Deploy" crashed outright. After that, the packaging step added: after building, automatically play one level with the exported version and check the exit code. Part 4 covers that crash in detail.
Practices from day one
| Practice | Reason |
|---|---|
| Have the AI clarify purpose, art source, gameplay form, and first-version scope before kickoff | These answers determine copyright rules, the asset pipeline, and the day-one deliverable |
| After the engine is decided, research platform support and package limits first, then schedule a real-device verification | Mini-game platforms have thin Godot support; problems only surface on real hardware |
| Decide vertical or horizontal early | The later the switch, the more rework on maps, UI, and screenshots |
| Build test, lint, auto-play, and frame capture before writing gameplay | The AI can't see or play; these tools let it find most problems itself |
| Turn the AI's own mistakes into an automated check in the command line | The same kind of problem won't slip through twice |
Next article covers gameplay: how each playtest comment became the infinite level, out-of-match progression, and reinforcement-deploy systems.