← All games

The Bell of Ages

An original 3D action-adventure for the browser about a boy, a forgotten song, and a kingdom in two ages, built with TypeScript, Three.js, and a scripted Blender pipeline.

Alder raises his shield as the Cinder Colossus winds up inside a golden warning ring.
Facing the Cinder Colossus, from The Bell of Ages README.

Alder is eleven. His father Tomas, keeper of the great bell, went to mend it last autumn and never came home. On the morning of the lantern festival, the bell sounds its first warning, and the village falls quiet.

Take up a practice sword and your father’s reed flute. Follow the pale paths out of Alder Village into the Whisperwood, up Cinderpeak, and down to the Larkwater Coast. Solve each sanctuary’s trial, break its guardian seal, and face the warden at its heart. When three relics rest in the altar, the Bell of Ages offers a crossing that costs seven years of your life.

The Bell of Ages is an original adventure inspired by classic 3D action-adventure games. Its world, characters, story, models, and music are original to the project, and it runs in a browser.

Sword, shield, and the golden ring

Chain a diagonal cut, a return cut, and a heavier thrust. Damage comes from the blade itself: each swing traces the sword’s real path against enemy hit volumes, so a miss is really a miss, and a blade that hits a wall glances off in sparks. Guardians telegraph every attack with a pulsing golden ring and commit to their facing, so a well-timed shield or dodge always has an answer. Lock-on keeps a single foe in focus.

Seven sanctuaries each run from a puzzle chamber to a sealed guardian hall to a warden’s arena, and each asks something different: touch memory stones in the order the roots remember, push a stone onto a seal, echo a melody on the three-note reed flute, turn star mirrors toward the north, balance light and shadow across three flames, or ring bells in the order an inscription names.

A kingdom in two ages

Before the crossing, you make your oldest friend Mira a promise: “I’ll find my way home” or “I’ll remember us as we are.” The choice changes your reunion, the memories in your journal, and the ending. As an adult you’re taller and stronger and carry the keeper’s longsword. The kingdom’s light has changed, and new sanctuaries wake in its far corners.

The campaign spans ten regions on one continuous overworld, seven sanctuaries and wardens, sixteen story scenes, one meaningful choice, and optional chests, wandering lights, and a sword upgrade.

More screenshots

What it’s built with

The game is TypeScript on Three.js r186, built with Vite into plain static files. A few engineering choices do most of the work:

  • One height function. Terrain rendering, character grounding, and camera clearance all sample the same deterministic function, so nothing floats or sinks.
  • Swept collision. Movement and dodge rolls are swept circles against rotated boxes and tree trunks in a spatial hash, so fast rolls can’t tunnel through fences, and you slide along walls instead of sticking.
  • Blade-accurate combat. The sword’s base-to-tip segment is sampled at 120 Hz across each swing and tested against enemy capsules, so hits that fall between frames still count.
  • A camera that respects walls. The follow camera casts against obstacle heights, retracts immediately, eases back out, and re-checks its smoothed position so it can’t clip through a corner.
  • Rendering on a budget. Static scenery is batched by material and spatial cell, vegetation is instanced, wind-animated in the shader, and swapped to lighter versions at a distance, and an adaptive mode lowers 3D resolution under load before trimming effects.

There are no audio files. Every sound, from flute notes to sword swings, is synthesized with the Web Audio API.

How it was made

All 31 models, including cottages, the sanctuary, a dungeon kit, props, trees, characters, and the warden, come from one deterministic Blender Python script, along with their procedural texture atlas. glTF Transform then compresses the export with Meshopt and WebP, from 13.3 MB down to a 2.4 MB runtime pack that passes the Khronos validator with zero errors. Two painted textures were made with an AI image-generation tool, with prompts recorded in the repository.

The game was developed with AI coding assistants following OpenAI’s guide to building games with Astra, with 30 Vitest tests covering progression, story, saves, assets, collision, and combat, plus scripted in-browser checks. The trailer and screenshots are reproducible. A Playwright harness runs the game under a fake clock, so every frame advances the simulation by exactly 1/30 second, and records the game’s own Web Audio output through an offline audio context.

Play it

The Bell of Ages is a playable prototype at v0.1.0, with a complete story from opening to epilogue. Download the web build, unzip it, and serve the folder with any static file server, then open it in a desktop browser with WebGL 2. Keyboard and mouse are recommended. The README is upfront about its limits: all seven sanctuaries share one three-chamber layout, the wardens share one model, and there’s no gamepad support yet.

Browse the source on GitHub. GitHub records the repository’s creation on October 4, 2026.

See it in action

The Bell of Ages trailer

The 1:41 trailer, with the game's own sound effects and a score arranged from its synthesized flute, chime, and ambient voices, plus on-screen captions; there is no voice acting. Everything is captured from the real game under a deterministic clock. Re-encoded here at 540p. Full-resolution original on GitHub

Keyboard shortcuts

Shortcuts stay out of text fields. Extra shortcuts are off until you enable them on this device. Ctrl or Command K is always available.

?
Open this help
Ctrl / ⌘ K
Open site search
Alt A
Browse articles
Alt R
Open your reading list
Alt T
Browse topics
Escape
Close dialogs or leave article focus mode