Vibe Coding on a Tight Leash: Inside anthonywu/ghost-invaders-game

How a strict Markdown spec and a zero-dependency architecture turned an AI coding session into a masterclass in procedural generation.

7 min read • View on GitHub • More from anthonywu

A mechanical robotic hand holding a drafting pen, clamped by a heavy brass compass, drawing a perfect wireframe arcade cabinet.
A rigid architectural blueprint successfully constrains erratic AI code generation.
Key Takeaways

The Architect and the Agent

Most AI-generated games devolve into unmaintainable spaghetti code. They rely on bloated frameworks to mask a lack of structural integrity. Ghost Invaders takes the opposite approach. It proves that artificial intelligence is best utilized not to hack a game together, but to execute a rigid engineering vision.

The repository relies on a foundational document named SPEC.md. This file acts as an unyielding architectural blueprint. By feeding this ground-truth document to an LLM, the developer forced the generation of clean, decoupled TypeScript. The result is a strict separation between the core game loop in Game.ts and the DOM manipulation layer.

The decoupled architecture keeps the core game engine entirely separate from DOM rendering.

Drawing with Math, Not Pixels

Traditional browser games rely on heavy asset pipelines. Developers load folders full of PNG sprites and manage complex caching strategies. Ghost Invaders abandons this model entirely in favor of raw mathematics.

A metallic stylus carving the geometric outline of a fighter jet into a blank canvas, surrounded by floating X and Y coordinates.
Rendering entities via raw Canvas math eliminates the need for external image assets.

The player's ship, modeled after an F-35 fighter jet, is drawn entirely using Canvas 2D API methods. The engine executes a series of precise coordinate plots sixty times per second. A custom particle system handles the engine exhaust, calculating unique trajectories for individual smoke particles without ever loading an external graphic.

ctx.beginPath();
ctx.moveTo(x, y - 15);
ctx.lineTo(x + 10, y + 10);
ctx.lineTo(x - 10, y + 10);
ctx.closePath();
ctx.fillStyle = '#A0A0A0';
ctx.fill();

The Procedural Audio Synthesizer

The most impressive technical feat lies hidden in the audio system. Rather than burdening the application with static audio files, the developer built a procedural synthesizer using the Web Audio API.

A split composition showing a heavy vinyl record crushing a table on the left, and a glowing tuning fork emitting sound waves on the right.
Procedural audio generation provides infinite variability with zero network overhead compared to static files.

A ten-line function creates the distinct laser sound by passing a sawtooth oscillator through a biquad filter. A mathematical frequency ramp drops the pitch rapidly, mimicking a classic arcade blast. The engine even calculates the exact spatial position of an enemy on the canvas and dynamically pans the generated sound between the left and right stereo channels.

Engineering for the Playground

Technical purity often comes at the expense of user experience. Here, the strict constraints serve a specific audience. The game is explicitly designed for children, featuring mechanics that prioritize accessibility over punishment.

A sophisticated scaling mechanism locks the canvas to an 800:1200 aspect ratio, ensuring consistent physics across any device screen. Furthermore, a state machine manages a powerful board-clearing ability on a sixty-second cooldown. This provides younger players with a guaranteed escape mechanism, proving that rigid mathematical architecture can still produce genuine fun.