TwinBar — Project Story

Inspiration

I originally built TwinBar in 2023 with Phaser 2 — a simple but brutally challenging arcade game where two pivots connected by an bar orbit around each other, and you tap to swap which ball is the pivot. Navigate a star while dodging bombs. For this hackathon I migrated the entire codebase from Phaser 2 to Phaser 4, modernizing the stack with Vite + TypeScript strict mode while keeping the core mechanic intact.

What I Learned

Phaser 4 is not Phaser 2. The upgrade from Phaser.Game(500, 750, Phaser.CANVAS) to Scale.RESIZE with a CSS-flexbox container was liberating — the game adapts to any screen without hardcoded dimensions. But Arcade Physics in Phaser 4 has subtle differences. I also struggled with typescript type definitions.

How I Built It

Core game (MainScene.ts, Grid.ts, Align.ts) — The twin-bar orbit loop runs each frame: position the orbiter via Math.cos/Math.sin around the pivot at fixed distance, check wall bounds with a manual circle-vs-rect check, update moving bombs with Math.sin-based oscillation. A frame-delta clamp prevents teleportation during tab-switch spikes. Tap to swap; overlap star to win; overlap bomb to lose.

Level system (levels.ts) — A typed LevelConfig[] array with 25 entries, each specifying bomb grid indices, star position, pivot location, and moving-bomb parameters. Grid math is a clean 10×15 row-major system (Grid.centerAt(index) converts grid index to pixel coordinates).

Challenges — Level Design

I spent most of my time on level design. The original had 5 buggy levels. The new version has 25 hand-tuned stages, from introductory bomb placements to late-game moving bombs that ping-pong across the arena. I built an autonomous solver — a Monte-Carlo AI that reruns the full physics in TypeScript, playing thousands of simulated games per level.

What's next for twinbar

I am looking forward to bring more challenging levels soon.

Built With

Share this project:

Updates

Submission history