Show HN: I made a Mario Galaxy game with Claude Code and Three.js in 53 days (supertommy.com)
Architecture:
- Custom SoA ECS for cache-friendly iteration, zero allocations in hot loops. Benchmarked against bitECS/miniplex.
- Process manager inspired by Game Code Complete's but data-oriented so processes are pure data, systems contain the logic.
- Multi-field gravity with 5 types (point, parallel, segment, cylinder, convex hull) with spring-damped transitions between fields.
- Rapier3D WASM with SIMD. Gravity-aware fake shadow system for playability.
- WebGL 2 shared context between Three.js and Pixi.js.
- Debug editor for placing objects, configuring settings, visualizing colliders, etc (Tweakpane + Three.js helpers)
76K lines of TypeScript. 735 commits. Runs on mobile. Plays best with gamepads.
The AI Process:
Claude Code (Opus) wrote ~95% of the code. I provided architecture, constraints, and direction; looked at some but not much of what it wrote.
My process for every feature: braindump what I want, relevant technical details, and "does this make sense?" into the chat. Largely unorganized. I built custom Claude Code skills like /lets-build:plan that spawns sub-agents to research the codebase first, then asks me clarifying questions. We go back and forth until it sounds right, then Claude writes plan documents split into phases so the app stays runnable after each one.
As we got closer to ship date, I started having Claude review its own plans. This mostly catches the main issues. Built dedicated skills for that too: /review-plan, /code-review, /retrospective, /ecs-review.
Where Claude struggled:
- It defaulted to OOP in TypeScript even though the project is data-oriented ECS. Took a lot of steering to overcome. Built /ecs-plan and /ecs-review skills specifically to catch and fix this.
- Level design failed completely. I tried making a CLI tool so Claude could help place objects in 3D space where "down" could be anywhere. Tried elevation maps, architectural diagrams; didn't help.
- At one point it had an index.ts that was thousands of lines long so ensuring a fast first paint was a disaster. I started refactoring manually but then felt it was a giant waste of my time to do it. So I had Claude map the dependency tree and do the refactor which was a piece of cake for it.
The hardest problems were the camera and the gravity shadows. Both work but still have edge cases. Galaxy's camera also has problems; part of that might be inherent to arbitrary gravity directions. The shadows are all fake, cast based on gravity field type, and the letter shapes (M, R) create concave, irregular geometry that Galaxy didn't have for planetoids.
87 plans total, averaging 2-3 pages each. The CLAUDE.md project file is 164 lines of hard constraints learned from debugging sessions. Every constraint has a token massacre behind it.
One of the biggest "wins" is having Claude create tools that you would probably never do for a project with a deadline in ~50 days. That time tradeoff (or even impossibility) is no longer valid and this likely compounds even more for longer projects.
11 comments
[ 0.24 ms ] story [ 38.1 ms ] threadEDIT: Well except for maybe Hotel Mario on the CD-i. :)
76k lines in 53 days? Crazy. How much of the 95% did you end up rewriting?
> 87 plans total, averaging 2-3 pages each. The CLAUDE.md project file is 164 lines of hard constraints
164 lines of constraints... Did you build those up over time or write them upfront? I try to keep adding rules every time Claude does something dumb.
> It defaulted to OOP in TypeScript even though the project is data-oriented ECS
yeah Claude really wants to write OOP no matter what you tell it! true!
The constraints were built up over time as we did the project; claude.md also got pruned several times to move things around so it references other files as claude finds it needs that information
yea, I am looking into how I can maybe fine tune a model for a more data-oriented world view
on the fine tune... I feel like the gain probably isnt worth the maintenance vs just adding another constraint to the prompt. did you find concrete cases where prompting just couldnt get you there?