Builds / Rift Survivors

Rift Survivors

A browser survivor game with 173 League-inspired champions, deterministic simulation, and online co-op.

Language
TypeScript
Browser build
rift.carletti.work ↗
Updated
—
173champions
5packages
30Hz simulation
179tests passing

What it changed

What building it taught me.

It started as a survivor clone and became the project where I had to make architecture, performance, and multiplayer work together.

01 / Architecture

Separate the game from the engine.

The simulation is a pure TypeScript package with no DOM, network, or clock. Content, client, server, and shared protocol sit around it. That split made the same simulation run in a browser worker and a Node server, and it made tests possible without a renderer.

02 / Determinism

Make the run reproducible before making it pretty.

The game runs at a fixed 30 Hz with a seeded RNG, pooled struct-of-arrays stores, and a spatial hash. Deterministic snapshots let me test the same seed twice, add a headless balance bot, and reason about networking without guessing.

03 / Performance

Design for the horde.

Hundreds of enemies and projectiles forced me to avoid per-frame allocations, reuse entity slots, cap pools, and rebuild a coarse flow field every 12 ticks instead of running pathfinding for every enemy. I learned to measure the simulation, not just the frame rate.

04 / Multiplayer

Treat disconnects as a normal state.

The co-op server is authoritative, sends full and delta snapshots, and the client interpolates between ticks. Reconnect, resync, bad messages, and a dropped player all had to be handled explicitly. It changed how I think about state that is shared by several clients.

05 / Content systems

Move the roster out of the code.

173 champions, upgrades, enemies, and stages are typed data validated at startup. Rulesets select systems, registries resolve behaviours by id, and save files have versioned migrations. Adding a champion no longer means editing the tick loop.

06 / Delivery

Keep the whole workspace green.

TypeScript strict mode, Biome, a CI workflow, and 179 passing tests made the larger changes possible. The documentation, ADRs, and handoff notes were part of the engineering, not cleanup after it.

Still open

The next pass.

The browser build is moving to rift.carletti.work. Matchmaking is not set up yet, unique moves still cover the original eight champions, and co-op needs more human playtesting.