Skip to content
← All work

06ONE TINY VILLAGE. ONE VERY BAD IDEA./Web Game

SNOWBALL

A low-poly 3D winter game about rolling one tiny snowball through a village and growing into an absolute unit.

Role
Creator & Developer
Stack
Three.js / JavaScript / Vite / Blender
Year
2026
Status
Shipped

01Context

A self-contained 3D arcade game with a deliberately simple hook: turn one small snowball into the largest thing in a winter village.

02Problem

Make a quick-to-understand rolling game feel expressive and replayable while coordinating movement, collection, collisions, camera response, and a changing 3D world across desktop and touch devices.

03Constraints

  1. 01Keep the game client-only, with no API, database, or server-side game state.
  2. 02Make keyboard, gamepad, mouse, and touch controls work across desktop and narrow mobile layouts.
  3. 03Hold responsive frame times across a range of GPUs while rendering snow, weather, shadows, post-processing, and a populated village.
  4. 04Keep run progress, daily-goal progress, graphics settings, and accessibility preferences useful without account creation.

04Architecture

Vite builds a static browser game whose Three.js renderer and modular GameEngine coordinate player motion, physics, environment, scoring, audio, and DOM-based overlays. Small persistence helpers store personal settings and run records in localStorage.

GameEngine and player
Coordinate the update loop, run states, snowball deformation, camera modes, and tracking for collected props.
Terrain and collision
Share rolling terrain and collision data across snowball motion, obstacles, props, and camera placement; resolve collection, impacts, and wall slides.
World and atmosphere
Build the alpine village, NPC actors, snow and wind particles, and stage-based changes to weather, fog, lighting, and sound.
Scoring and controls
Combine combos, near misses, frenzy, momentum boost, daily goals, and stage progression with keyboard, touch, and gamepad input.
Settings and audio
Provide adaptive quality presets, dynamic resolution options, a post-processing toggle, synthesized Web Audio effects, and procedural music.
Local game state
Persist best score, best time, graphics preferences, and reduce-motion settings in the browser.

05Decisions

D1Keep the game as a static, client-side application

Why

The run, score, and personal settings do not require a server round trip or account service.

Result

The game can be hosted from static assets while keeping its state and interaction in the browser.

D2Split world, physics, player, scoring, audio, and UI into modules

Why

A single loop coordinates these systems, but separate modules make each part easier to tune as the game grows.

Result

Game behavior, scene construction, persistence, and overlays remain distinct parts of the Vite application.

D3Pair procedural models with a small set of sculpted terrain assets

Why

Code-built village props keep the world flexible, while authored mountain silhouettes add a stronger horizon.

Result

The game mixes lightweight generated scene objects with custom Blender mountain meshes and a fallback terrain form.

06Trade-offs

Layered atmosphere and post-processing around a low-poly world

Gained

  • +A clear visual identity that reads from the overview camera
  • +Weather and lighting can change over the course of a run

Gave up

  • −Particles, shadows, and bloom need scalable quality settings for slower hardware

Store progress and preferences locally in the browser

Gained

  • +No account step or backend dependency
  • +Settings and best runs are available immediately on the same device

Gave up

  • −Scores and preferences do not sync across devices

07Performance

  • ↯Offer low-to-ultra graphics presets and individual controls for shadows, resolution, particles, draw distance, and post-processing.
  • ↯Use dynamic resolution scaling as an option when maintaining frame time matters more than native render resolution.
  • ↯Split the Three.js dependency into a dedicated vendor chunk and leave the game's own bundle separate.

08Challenges

  • #Keep custom snowball dynamics, terrain height, collected props, and collision responses aligned as the ball changes size and speed.
  • #Balance camera framing and control responsiveness between a wide desktop scene and thumb-operated mobile layouts.
  • #Keep increasingly intense snow, wind, fog, lighting, and audio in step with stage progression while allowing graphics to scale down.

09Learnings

  • →A compact game loop can feel rich when collection, near misses, momentum, collisions, and character reactions give each movement a readable response.
  • →Controls and rendering quality need device-aware defaults when the same 3D scene serves keyboard, gamepad, and touch players.
  • →Separating physics, world, audio, scoring, settings, and UI makes a growing client-side game easier to tune without adding a backend.

10Retrospective

A future pass could expand device-specific performance profiling and save optional run replays alongside the current local bests and daily goals.

Next project · 01

HELLO WORLD UNIVERSE →

A visual and technical anthology of computational history across programming languages.

HELLO WORLD UNIVERSE Thumbnail