Phaser AE

Endless runner core

Pro packv3.0.0-1Arcade

The run every endless runner shares, as plain state: chunks of world laid ahead by seed, a speed that climbs to a cap, stumbles that bring the chaser, crashes that end it, a score for distance and coins, and timed power-ups. Your game moves the runner; this pack owns the distance and everything that follows from it.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 19, 2026 · updated October 20, 2026

Endless runner core: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

What it does

A run is a single number, the distance along it, and the rules that hang off that number. You call run.step(dt) once a frame and move your runner by run.state.speed. The core keeps the timers, ramps the speed, counts the score, and lays chunks ahead of the runner while dropping the ones far behind. When your collision code decides the runner touched something, you call run.hit('stumble') or run.hit('crash'), and the core answers 'ignored', 'shielded', 'stumbled' or 'over'.

The world is made of chunks you author: a length, your own content in items, and rules for when the chunk may appear. A weight sets how often it is picked, from and until set the distances it may start between so harder chunks arrive later, and follows and never decide what it may come straight after (a breather after a train yard). If nothing fits every rule, the choice relaxes rather than stopping. The core never reads a chunk's items, so lanes of trains, a turning temple path and a corridor of zappers are all just different data on the same run.

Power-ups are named definitions with a duration and any of a shield, invulnerability, a score multiplier and a speed factor; a duration of 0 makes a shield that waits for its hit. Events since the last frame come from run.drain(): new chunks, coins, stumbles, the end of the run, power-ups starting and ending, and milestones. The whole run saves to plain JSON with snapshot and comes back with restore, and validateRunner lists every fault in a set of options before a run starts.

Features

  • Seeded chunks — authored pieces of world with weights, distance bands, no-repeat spacing and follow rules, laid ahead and dropped behind.
  • An opening — named chunks played first, in order, before the seeded choice takes over.
  • A speed ramp — from a start speed to a cap, gaining by time or by distance.
  • Stumbles or one-hit deaths — a stumble slows the runner and brings the chaser, two inside a window catch them; or set every hit to end the run.
  • Power-ups — timed or waiting shields, invulnerability, score multipliers and speed factors, with refresh, extend or ignore on a second pickup.
  • Score and coins — points per unit run and per coin under a multiplier, counted as the run goes so a doubler counts only while it lasts.
  • Revives and protection — carry on after the end with the chaser gone, or grant a few seconds of safety after a landing.
  • Events and milestones — a drained list of what happened since the last frame, with a milestone every so many units.
  • Saves and validation — the run as plain JSON, and every fault in its options named before it starts.

Good for

  • Lane runners that swipe between tracks past trains and barriers, in the style of Subway Surfers.
  • Turning-path runners with corners, jumps and slides, in the style of Temple Run.
  • Side-on jetpack runners through corridors of hazards, in the style of Jetpack Joyride.
  • Your own endless runner, in 2D or 3D, where you write the motor and keep the run rules.
  • Score-chasing mobile games that need distance, coins, multipliers and revives without building them again.

Make it yours

Every run takes its own options; the pack itself has none. You set the chunks and the opening, the seed, how far chunks are laid ahead (default 150) and kept behind (default 30), a gap between chunks and noRepeat spacing. speed takes a start, a maximum and an acceleration by time or distance (default 10 to 30, gaining 0.15 a second). hits chooses between 'stumble' and 'kill'; stumble sets the chaser's window, the stumbles that catch the runner, the slowdown and its recovery; grace sets the safe time after a shield breaks or a revive. powerUps are yours by name, score sets points per unit and per coin, and milestone sets the event spacing. The defaults are in runnerDefaults.

Two different runs: a forgiving lane runner with a hoverboard shield, a magnet and a doubler, where two scrapes inside four seconds let the chaser catch you; and a hard one-hit runner with hits: 'kill', a speed ramp by distance, no power-ups and score from coins alone.

A quick look

A run with an opening chunk, a breather that follows trains and three power-ups:

const run = createRunner({
    seed: 4, opening: ['runway'],
    chunks: [
        { id: 'runway', length: 60, weight: 0, items: [] },
        { id: 'trains', length: 80, items: trainsPattern, tags: ['trains'] },
        { id: 'coins', length: 40, items: coinArc, follows: ['trains'], weight: 2 },
    ],
    speed: { start: 12, max: 28, accel: 0.12 }, stumble: { window: 4, limit: 2 },
    powerUps: { hoverboard: { duration: 30, shield: true }, double: { duration: 15, multiplier: 2 } },
});
run.step(dt);
if (touching(trainFront)) run.hit('crash', 'train');

Works with

  • lane-runner-3d — a lane runner with trains, barriers, jumps and rolls, built on this core.
  • turn-runner-3d — a runner on a path that turns and forks, built on this core.
  • jetpack-runner-2d — a jetpack corridor of zappers, lasers and missiles, built on this core.
  • rooftop-runner-2d — rooftops with gaps and crashing obstacles.
  • ninja-rope-2d — for a finite course to a goal rather than an endless run.

Good to know

  • It moves nothing and tests no collisions: your motor moves the runner, decides what touched what, and calls hit, coin and power.
  • Distance is one number. A world that branches maps the same distance to whichever branch was taken, and the chunks ahead do not depend on the choice.
  • The chunk choice is the only randomness. A motor that randomises inside a chunk should use its own seeded stream so saves still replay.
  • At most 512 events are kept between drains, and a chunk's items are kept by reference, so do not change them during a run.

More Arcade packs

Show all →