logo
Unlock

Install with the CLI:

bjs download AutoRunnerDirector

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 have startLives spare cars, plus one for every extraCarEvery points. Lose a car with none left and the game is over.
  • Wreck a civilian or a police car and you score nothing for civilianPenalty seconds: no distance points and no kill points.
  • Every levelLength metres the level goes up. The spawner is told the new level and sends more traffic and worse enemies.
  • A weapons truck comes at firstTruckAt metres, then every truckEvery metres. From level helicopterFromLevel, a helicopter comes about every helicopterEvery seconds.
  • 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:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add AutoRunnerDirector
    bjs download AutoRunnerDirector

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Game": {
    "tags": ["world"],
    "components": {
      "AutoRunnerDirector": {
        "player": "Player",
        "freeCarSeconds": 120,
        "startLives": 2
      }
    }
  }
}

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:

TypeScript
/** Level for a distance driven. */
export function levelFor(distance: number, levelLength: number): number {
  return 1 + Math.floor(Math.max(0, distance) / Math.max(1, levelLength));
}

/** How many extra cars a score has earned. */
export function extraCarsFor(score: number, every: number): number {
  return every > 0 ? Math.floor(Math.max(0, score) / every) : 0;
}

/** Points for distance: whole points per metre, carrying the remainder. */
export function distancePoints(metres: number, perMetre: number, carry: number): { points: number; carry: number } {
  const raw = Math.max(0, metres) * perMetre + carry;
  const points = Math.floor(raw);
  return { points, carry: raw - points };
}

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:

TypeScript
export const KILL_POINTS: Record<string, number> = {
  rammer: 150,
  gunner: 300,
  shover: 500,
  helicopter: 750,
  enemy: 150,
  civilian: 0,
  police: 0,
};

The most specific tag wins, so a car tagged both enemy and gunner is worth 300.

Settings

FieldDefaultWhat it does
player"Player"The player's car entity.
freeCarSeconds120Seconds at the start when a lost car comes back free.
startLives2Spare cars once the free time is over.
extraCarEvery15000One more spare car for every this many points. 0 turns it off.
pointsPerMetre1Points for each metre of new road.
civilianPenalty6Seconds of no score after you wreck a civilian or a police car.
levelLength1500Metres per level.
truckEvery1500Metres between weapons trucks.
firstTruckAt500Metres to the first weapons truck.
helicopterFromLevel3First level with helicopters.
helicopterEvery45Seconds between helicopters, give or take a fifth.
respawnDelay2.4Seconds between losing a car and getting the next.
invulnSeconds2.5Seconds a fresh car can't be hurt.
killCredit4A wreck is the player's if they hit that car in the last this many seconds.
startHour15.5Hour 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

EventPayloadDirection
autoRunner.state.changed{ state, previous }, state is title, playing, dying, gameover or pausedemits
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 bademits
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 secondemits
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.

More like this

AutoRunnerBomber
AutoRunnerDriver
AutoRunnerHUD
AutoRunnerProjectile
AutoRunnerWeapons
CarCollision
CarDrive
DayNightCycle
Health
HighwayRoad
HighwaySpawner
KeyboardInput
Mesh
MeshPrimitive
RoadHazard
SupplyTruck
AiDriver
BallPossession
BallReset
BilliardRack
BilliardTurns
BoatMode
BoatWater
CaptureZone
CarPaint
ConicPath
ContactDamage
ContactImpulse
Enemy
Flipper
Goal
Headlights
PlayerInput
Plunger
PointerDrag
RespawnTimer
RoadAudio
RoadCamera
RoadFX
RoadSpawner
RoadTreadmill
RoadsideScenery
RoundReset
Scoreboard
SmokeScreen
SoccerDirector
SpaceGolfDirector
SurfacePatch
TrafficConvoy
TrajectoryPreview
TwinStickShooter
WeaponsVan

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search