π Whirlbird on Steroids
A first-person 3D balloon-flying game that lives inside Reddit β fly through a metallic space corridor, dodge obstacles, thread arches, rack up points, and publish your score for the whole subreddit to see.
π‘ Inspiration
The original Whirlbird was a charming side-scrolling balloon game. I asked: what if we cranked it up to 11? β full 3D, first-person perspective, a deep-space corridor, and the social layer of Reddit baked right in. The result is an adrenaline-fuelled flying game you can play without ever leaving your feed.
π What It Does
| Feature | Details |
|---|---|
| 3D Flight | First-person chase-cam through a procedurally-spawned space corridor |
| Lane-Based Obstacles | Trees, rings, and arches spawn across 5 lanes with progressive difficulty |
| Arch Rules | You must fly through arches β flying past one is game over |
| Leaderboard | Top-3 scores stored server-side in Redis and displayed on the splash screen |
| Publish to Reddit | One tap to post your score as a reddit custom post so the community can compete |
| Responsive | Plays on desktop (WASD / Mouse) and mobile (touch / tilt) |
| Space Environment | Starfield, metallic corridors, nebula clouds, ACES filmic tone mapping |
π How I Built It
Client (Three.js + TypeScript)
βββ game.ts β main loop, camera, physics, score, UI overlays
βββ obstacles.ts β lane-based spawner, object pooling, difficulty curves
βββ splash.ts β leaderboard fetch, animated splash UI
βββ game.html/css β HUD, loading screen, game-over, publish modals
Server (Hono + Devvit)
βββ index.ts β security middleware, error handler, 404 catch-all
βββ routes/
βββ api.ts β /init, /score, /leaderboard, /publish
βββ menu.ts β moderator menu actions
βββ triggers.ts β onAppInstall auto-post
βββ forms.ts β devvit form handling
Shared
βββ api.ts β TypeScript interfaces shared between client & server
Key architecture decisions:
- Object pooling for obstacles keeps the garbage collector quiet at 60 fps
- Lane system (5 lanes, 3 units apart) guarantees playable paths exist
normalizeModel()auto-scales any GLB to a target bounding box β no manual fiddling- Redis sorted sets for the leaderboard β O(log N) upserts, O(N) range queries
- Security-first middleware β content-type enforcement, rate limiting, input validation, no stack-trace leaks
π§ Challenges We Ran Into
- GLB model sizing β models came in wildly different scales; solved with bounding-box normalisation
- Arch collision detection β detecting whether the balloon flew through vs over/beside an arch required a two-zone box approach (
ARCH_HALF_W,ARCH_OPEN_H) - Devvit platform constraints β no
window.alert, limited DOM APIs, custom post rendering, Redis-only persistence - Rate-limit races β concurrent score submissions could bypass a naΓ―ve in-memory limiter; Redis timestamps solved it
- Responsive 3D β getting FOV, touch controls, and CSS to behave across phone and desktop inside a Reddit embed
π Accomplishments We're Proud Of
- Full publish-to-subreddit flow: play β score β confirm β post appears on the feed
- Chaos engineering test suite validating boundary values, malformed input, Redis failures, and rate-limit hammering
- Zero
anytypes β every interface hasreadonlyproperties and explicit return types - Loading screen with real progress bar tracking individual GLB asset loads
- Security hardened: OWASP-aligned headers, content-type guards, bot-proof rate limits, username sanitisation
π What We Learned
- Chaos engineering β hypothesis-driven fault injection catches bugs unit tests miss
- Playwright POM β page objects + role-based selectors keep E2E tests maintainable
- Three-layer API thinking β validate on both client and server, never trust the wire
- Security as a first-class feature β rate limiting, input validation, and header hardening are table stakes, not afterthoughts
- Object pooling matters at 60 fps β one stray
new THREE.Mesh()in the hot loop and you feel it
What's Next
- More obstacle types β spinning blades, moving platforms, gravity wells
- Power-ups β shield, magnet, speed boost
- Multiplayer ghosts β see other players' replays in real time
- Daily challenges β curated obstacle sequences with unique leaderboards
- Sound design β spatial audio for whooshes, dings, and the satisfying arch pass chime
- Achievement badges β Reddit flair for milestones (100 arches, 1000 score, etc.)
Built With
- devvit
- eslint
- hono
- playwrite
- redis
- three.js
- typescript
- vite
- vitetest
Log in or sign up for Devpost to join the conversation.