Building Slice Balloon With AI in Under 10 Minutes

While rebuilding ianpiggott.com as a static Astro site, I wanted a small arcade game on the contact page — Taito Crazy Balloon vibes: steer up and down, drift through gaps, don't pop on the spikes.

I described that to Grok (xAI) in Cursor. First playable build: under ten minutes. One Astro component, one canvas, zero game-engine dependencies. What follows is how it works, what broke, how we tuned it, and what AI-assisted dev actually looks like in 2026.

Canvas 2D Astro component Crazy Balloon-style Grok / Cursor <10 min first build No Unity
1Astro file
0game npm deps
3lives
~10mto playable

The brief

Genre

Vertical steer-only balloon through scrolling wall gaps. Crazy Balloon-style — not a Flappy Bird clone.

Stack

Embed in existing Astro layout. Match site CSS variables and typography.

Input

Keyboard (arrows / W-S), click-to-start, touch ↑/↓ hold buttons on phones.

Output

Static HTML — game logic in an inline client script. No server runtime.

A static site generator changes what "shipping a game" means: you're not deploying a WebGL build — you're dropping a component next to the contact form.

What shipped in the first pass

Four layers, one file

Grok scaffolded SliceBalloonGame.astro:

  1. Markup — HUD, canvas, start overlay, touch bar
  2. Script — TypeScript game loop in <script> (bundled by Vite)
  3. Styles — scoped CSS using --color-header, --color-accent, etc.
  4. Integration — import on contact.astro, boot on astro:page-load

Core architecture

// Fixed player, scrolling world
const BALLOON_X = 72;       // screen X never changes
let worldX = 0;             // increases each frame
const sx = wall.x - worldX; // wall screen position

function loop() {
  update();
  render();
  requestAnimationFrame(loop);
}

The balloon stays at a fixed X. Obstacles live in world space and slide left. Simple collision: the player is a fixed probe; the world moves past them.

Play it

Score: 0Lives: 3

Arrow keys or W/S to steer up and down. On phone, hold the up/down buttons.

Open on contact page Try Slice Invaders too

Under the hood

Render pipeline

Pure Canvas 2D — no Pixi, Phaser, or Three.js. Each frame:

  1. drawSky() — gradient
  2. drawClouds() — parallax
  3. drawEdges() — ceiling/floor spikes
  4. drawWall() — brick columns + gap spikes
  5. drawBalloon() — body, string, basket

Obstacle model

type Wall = {
  x: number;
  gapY: number;
  gapH: number;
};

Spawn horizon ahead of camera; cull walls off the left edge. Gaps randomised in a safe band — every column is passable.

Collision

Softened AABB hitbox — slightly narrower than the drawn ellipse for fair near-misses.

Three deaths: ceiling, floor, or wall outside the gap. Three lives, brief invincibility, small rewind after a pop.

Input & mobile

Desktop: Set<string> key polling in rAF. Touch: ↑/↓ hold buttons via @media (hover: none) — continuous thrust, not tap.

data-bg-ready guard + astro:page-load prevents double-binding on client nav.

Wall spawn logic (correct version)

function ensureWalls() {
  walls = walls.filter((wall) => wall.x - worldX > -WALL_W * 2);
  const horizon = worldX + W + SPAWN_AHEAD;
  while (nextWallX < horizon) spawnWall();
}

The bug that broke v1

Symptom

Endless sky, score ticking up, no deaths. Looked fine in a screenshot; felt broken in play.

Cause — inverted wall culling

// WRONG: deletes walls still approaching from the right
walls = walls.filter((wall) => wall.x - worldX < W + 80);

That kept walls with low screen X and deleted obstacles still off the right edge — garbage-collected before they reached the balloon.

Fix

walls = walls.filter((wall) => wall.x - worldX > -WALL_W * 2);

AI generated the game fast. I still had to play it to catch this. The vibe doesn't replace the playtest.

Tuning after the ten minutes

Human-in-the-loop polish

Playable in ten minutes; finished over a few conversation turns:

Slower scroll Wider gaps First wall further out Difficulty ramp

Score-based difficulty

function difficultyRamp() {
  return Math.min(score / DIFFICULTY_RAMP_SCORE, 1);
}

function currentScroll() {
  const ramp = difficultyRamp();
  return SCROLL_BASE + (SCROLL_MAX - SCROLL_BASE) * ramp;
}

function nextWallGap() {
  const ramp = difficultyRamp();
  const loose = WALL_GAP_MAX - 100 + Math.random() * 100;
  const tight = WALL_GAP_MIN - 20 + Math.random() * 55;
  return loose + (tight - loose) * ramp;
}

At high scores: faster scroll and two gap columns on screen — emergent pressure without a wave system.

Why Astro

Islands by default

Contact page is static HTML. Game hydrates only where imported.

One file

Markup, logic, CSS colocated — easy to reason about in chat with an AI assistant.

Static deploy

npm run build → game ships in dist/contact/index.html like everything else.

No server

100% client-side canvas. AI authored source; nothing to operate at runtime.

What AI accelerated

Task Traditional Grok in Cursor
Canvas boilerplate (loop, input, overlay) 1–2 hours ~2 minutes
Wall spawn + collision + draw 2–3 hours ~5 minutes
Astro embed + site styling 30–60 minutes ~3 minutes
Playtesting + feel tuning Still human Still human

AI didn't replace judgment on pacing, fairness, or the culling bug. It collapsed the distance between "idea" and "something running in the real layout."

File map

  • src/components/SliceBalloonGame.astro — entire game
  • src/pages/contact.astro — embed + credit aside
  • src/components/PostContent.astrodata-embed-game="slice-balloon" inline demo marker

Takeaways

  1. Constrain the AI — fixed stack, fixed scope, fixed reference (Crazy Balloon). Narrow prompts beat "make me a game."
  2. World-space scrolling with fixed player X — simple collision, easy to explain in chat.
  3. Ship inside the site — no separate game repo, no brand drift.
  4. Playtest immediately — coordinate bugs only show up when you play.
  5. Under ten minutes is real for a first playable. Polish is a conversation.

If you're rebuilding a personal site in 2026, this is now rational to add — not because games are free, but because scaffolding cost dropped by an order of magnitude. The spike walls are still deadly. Writing them is a lot faster than it used to be.

Game & embed by Grok (xAI) · Site by Ian Piggott · Play Slice Balloon