AutoRunnerDirector
Runs a game of Endless Rampage: the title screen, the score, the free-car clock, spare cars, levels, and what happens when you lose a car.
The rules
Put it on the world entity. Enter starts a run, and P or Escape pauses.
- You get a point for every metre of new road, and points for every enemy you put off it: rammed, shot, or spun out on your oil. Backing up earns nothing.
- At the start a clock counts down from
freeCarSeconds. Until it hits zero, a lost car comes back free. After that you havestartLivesspare cars, plus one for everyextraCarEverypoints. Lose a car with none left and the game is over. - Wreck a civilian or a police car and you score nothing for
civilianPenaltyseconds: no distance points and no kill points. - Every
levelLengthmetres the level goes up. The spawner is told the new level and sends more traffic and worse enemies. - A weapons truck comes at
firstTruckAtmetres, then everytruckEverymetres. From levelhelicopterFromLevel, a helicopter comes about everyhelicopterEveryseconds. - When a police chase starts you get a message, and another when the last car gives up.
Use it in a scene
A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.
Build it from scratch with the bjs CLI:
- 1Scaffold a project
World, renderer, and dev server — ready to run.
- 2Install dependencies
- 3Add AutoRunnerDirector
Copies its source into src/ so the scene resolves.
First time? Run bjs login once.
- 4Paste the scene into src/scenes/arcade-room.ts and run
SceneLoader builds the world from the JSON; reload to rebuild.
The director keeps running while the world is paused, or nothing could unpause it. A lost car is driven out of the back of the weapons truck when there is one. If no truck turns up, the car is handed back six seconds after respawnDelay runs out.
Score and spare cars
The score is three small functions in the core:
The carry is what keeps the score moving. At 30 m/s and 60 frames a second the car gains half a metre a frame, and rounding that down every frame would give zero forever. With the carry, the first frame returns { points: 0, carry: 0.5 } and the next returns { points: 1, carry: 0 }.
extraCarsFor counts from the whole score, not the last award: extraCarsFor(31200, 15000) is 2. The director remembers how many cars it has handed out and adds only the gap, so one big kill that crosses two marks gives two cars.
levelFor(3200, 1500) is 3, counted from where the run began. With the defaults, that is where helicopters start.
Who gets the kill
A car can be wrecked by something other than the player, and only the player's wrecks score. Each time the player rams a car (carCollision.hit), shoots it (autoRunnerProjectile.hit) or slides it on their oil (roadHazard.entered), the director notes the time. If health.died comes for that car within killCredit seconds, the kill is the player's, and the car's tags set the points:
The most specific tag wins, so a car tagged both enemy and gunner is worth 300.
Settings
| Field | Default | What it does |
|---|---|---|
player | "Player" | The player's car entity. |
freeCarSeconds | 120 | Seconds at the start when a lost car comes back free. |
startLives | 2 | Spare cars once the free time is over. |
extraCarEvery | 15000 | One more spare car for every this many points. 0 turns it off. |
pointsPerMetre | 1 | Points for each metre of new road. |
civilianPenalty | 6 | Seconds of no score after you wreck a civilian or a police car. |
levelLength | 1500 | Metres per level. |
truckEvery | 1500 | Metres between weapons trucks. |
firstTruckAt | 500 | Metres to the first weapons truck. |
helicopterFromLevel | 3 | First level with helicopters. |
helicopterEvery | 45 | Seconds between helicopters, give or take a fifth. |
respawnDelay | 2.4 | Seconds between losing a car and getting the next. |
invulnSeconds | 2.5 | Seconds a fresh car can't be hurt. |
killCredit | 4 | A wreck is the player's if they hit that car in the last this many seconds. |
startHour | 15.5 | Hour the day clock is set to when a run starts. Negative leaves it alone. |
hiScoreKey | "endlessrampage.hiscore" | localStorage key for the high score. Empty keeps no high score. |
Events
| Event | Payload | Direction |
|---|---|---|
autoRunner.state.changed | { state, previous }, state is title, playing, dying, gameover or paused | emits |
autoRunner.score.changed | { score, hiScore, delta, reason } | emits |
autoRunner.lives.changed | { lives, freeTime } | emits |
autoRunner.level.changed | { level } | emits |
autoRunner.message | { text, tone, seconds }, tone is info, good or bad | emits |
autoRunner.kill | { entityId, kind, points, x, z } | emits |
autoRunner.status | { state, score, hiScore, lives, freeTime, distance, speed, hp, maxHp, level, penalty, pursuers }, ten times a second | emits |
highwaySpawner.enabled.set | { enabled } | emits |
highwaySpawner.level.set | { level } | emits |
highwaySpawner.clear | {} | emits |
supplyTruck.dispatch | {} | emits |
supplyTruck.deliver | { entityId } | emits |
autoRunnerBomber.dispatch | {} | emits |
autoRunnerWeapons.enabled.set | { entityId, enabled } | emits |
autoRunnerWeapons.reset | { entityId } | emits |
carDrive.nudge | { entityId, dx, dz, dvx, dvz, dheading } | emits |
health.heal | { entityId, amount } | emits |
mesh.visible.set | { entityId, visible } | emits |
dayNight.time.set | { hour } | emits |
autoRunner.start | {} | listens |
autoRunner.pause | {} | listens |
keyboard.keydown | { code } | listens |
health.died | { entityId } | listens |
carCollision.hit | { a, b, x, z, closing, dvA, dvB } | listens |
autoRunnerProjectile.hit | { entityId, targetId, owner, kind, x, z, damage } | listens |
roadHazard.entered | { hazardId, entityId, kind, owner } | listens |
autoRunnerDriver.pursuit | { entityId, targetId, on } | listens |
supplyTruck.arrived | { truckId } | listens |
supplyTruck.delivered | { entityId, truckId } | listens |
supplyTruck.upgraded | { entityId, offer } | listens |
Needs
- CarDrive: the player's car. The director turns its keys on and off, reads its speed, and moves it back to the road with
carDrive.nudge. - CarCollision: rams that earn kill credit, and the ghost tag that keeps a lost car out of the traffic.
- MeshPrimitive: where each car is, for the road position and the kill pop-up.
- HighwayRoad: turns a position into metres along the road, and picks the middle lane for a new car.
- Health: when a car dies, and the heal and short shield a new car gets.
- SupplyTruck: the weapons truck it sends for, and drives a new car out of.
The director also sends orders to HighwaySpawner, AutoRunnerWeapons, AutoRunnerBomber and DayNightCycle. Leave one out and its orders go unheard.




















































