Phaser AE

Turning-path 3D runner

Pro packv3.0.0-33DArcade

The rules of an endless runner on a path that turns: swipe to take each corner, tilt to steer, jump and slide, and stay ahead of the chasers. The path, the runner's body, the speed and the power-ups are all options, and the pack hands your game world positions to draw.

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

Released October 14, 2026 · updated October 20, 2026

Turning-path 3D runner: 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.

The pack

turnRunner3d

function turnRunner3d(): Pack<{ turnRunner: TurnRunnerApi }>

The turn-runner-3d pack: game.turnRunner, Temple Run's rules on runner-core. No options.

Helpers

createTurnAutopilot

function createTurnAutopilot(game: TurnRunner, options: TurnAutopilotOptions = {}): TurnAutopilot

A turn run's autopilot. It only reads game; give its moves to game.input and its tilt to game.steer.

createTurnRunner

function createTurnRunner(options: TurnRunnerOptions = {}): TurnRunner

Start a turn run. Throws, with every fault, on options it refuses.

templeChunks

function templeChunks(options: { width?: number } = {}): RunnerChunk<TurnItem>[]

Temple Run's path as chunks: a start, straight stretches of roots to jump, fire, arches to slide under, gaps and broken edges, trees to steer round, weaving coin lines and power-ups, and stretches that end at a corner or a T-junction. Harder ones come further along. Every stretch leaves room after its last obstacle to swipe a corner.

turnBodyDefaults

const turnBodyDefaults: TurnBody

The body defaults.

turnRunnerPowerUps

const turnRunnerPowerUps: Record<string, RunnerPowerUp>

The built-in power-ups: Temple Run's.

validateTurnRunner

function validateTurnRunner(options: TurnRunnerOptions = {}): string[]

Check a turn run's options and chunks. Empty when it can be run.

Types

TurnAutopilot

interface TurnAutopilot

A player that picks the next moves and the tilt.

  • next(): TurnAutopilotPlan — What to do now. Call it before each step: it plans once every every, and steers every call.

TurnAutopilotOptions

interface TurnAutopilotOptions

How the autopilot looks ahead.

  • horizon?: number — Seconds a plan must live through. Default 1.6.
  • beyond?: number — Seconds it looks on past that, to choose between plans that live. Default 1.
  • times?: number[] — When a plan's jump or slide can come. Default [0, 0.2, 0.4].
  • every?: number — Seconds of run between decisions. Default 0.1.

TurnAutopilotPlan

interface TurnAutopilotPlan

What to do now.

  • moves: TurnMove[] — Moves to give input.
  • tilt: number — The tilt to give steer.

TurnBarrier

interface TurnBarrier

Something to jump, slide under or steer round, across part or all of the path.

  • kind: 'barrier' — Item type tag; always 'barrier' (a barrier).
  • at: number — Where it stands along the stretch, from its start.
  • bottom: number — The height of its underside: a sliding runner passes below it.
  • top: number — The height of its top: a jumping runner passes over it.
  • depth?: number — Its depth along the path. Default 0.4.
  • left?: number — Its left edge, across the path from the middle (negative is left). Default the path's left edge.
  • right?: number — Its right edge. Default the path's right edge.
  • look?: string — What it is, for the drawing: 'root', 'fire', 'arch', 'tree' or a game's own.
  • hit?: 'crash' | 'stumble' — What running into it does. Default 'crash'; a trip is 'stumble'.

TurnBarrierView

interface TurnBarrierView extends TurnThingView

A barrier, as drawn: where its middle is and its size.

  • width: number — Its extent across the path, in world units: its right edge less its left.
  • depth: number — Its depth along the path, in world units.
  • bottom: number — Height of its underside above the path, in world units.
  • top: number — Height of its top above the path, in world units.
  • look: string — What it is, for the drawing: the barrier's look, or 'barrier' when it has none.

TurnBody

interface TurnBody

The runner's body and moves.

  • height: number — Standing height. Default 1.8.
  • slideHeight: number — Height while sliding. Default 0.8.
  • halfWidth: number — Half its width. Default 0.3.
  • halfDepth: number — Half its depth along the path. Default 0.3.
  • jumpHeight: number — How high a jump goes. Default 1.5.
  • jumpTime: number — How long a jump is in the air. Default 0.7 s.
  • slideTime: number — How long a slide lasts. Default 0.75 s.
  • steerSpeed: number — How fast a full tilt moves the runner across. Default 5 units a second.
  • turnEarly: number — How far before a corner's middle a swipe takes it. Default 9.

TurnCoins

interface TurnCoins

A line of coins along the stretch, at one place across it or weaving.

  • kind: 'coins' — Item type tag; always 'coins' (a line of coins).
  • at: number — Where the first is.
  • count?: number — How many. Default 1.
  • every?: number — The spacing. Default 2.5.
  • across?: number — Where across the path. Default 0, the middle.
  • weave?: number — Weave from side to side this far either way, one sway per count. Default 0.
  • y?: number — Height. Default 1.
  • arc?: number — An arch this high over the middle coins. Default 0.

TurnCorner

interface TurnCorner

How the stretch ends: a corner one way, or a T-junction either way. Without one, the path runs straight on.

  • kind: 'turn' — Item type tag; always 'turn' (a corner).
  • dir: 'left' | 'right' | 'both' — Which way the path goes on.

TurnEvent

type TurnEvent = | RunnerEvent<TurnItem> | { kind: 'jump' } | { kind: 'slide' } | { kind: 'land' } | { kind: 'turn'; dir: 'left' | 'right'; heading: number } | { kind: 'trip'; id: string } | { kind: 'crash'; id: string; what: string } | { kind: 'fall' } | { kind: 'pickup'; id: string; x: number; y: number; z: number; power?: string }

Something that happened in a turn run: runner-core's events, and the motor's own.

TurnGap

interface TurnGap

A hole in the path: across all of it (a gap to jump) or part of it (a broken edge to steer past).

  • kind: 'gap' — Item type tag; always 'gap' (a gap).
  • at: number — Where it starts along the stretch.
  • length: number — How long it is.
  • left?: number — Its left edge across the path. Default the path's left edge.
  • right?: number — Its right edge. Default the path's right edge.

TurnItem

type TurnItem = TurnBarrier | TurnGap | TurnCoins | TurnPickup | TurnCorner

What a chunk of path holds.

TurnMove

type TurnMove = 'left' | 'right' | 'jump' | 'slide'

A move.

TurnPickup

interface TurnPickup

A power-up to pick up.

  • kind: 'power' — Item type tag; always 'power' (a power-up pickup).
  • at: number — Where along the stretch.
  • across?: number — Where across. Default 0.
  • power: string — The power-up it starts.
  • y?: number — Height. Default 1.

TurnPoint

interface TurnPoint

A point on the ground: x across, z along the start's heading.

  • x: number — World units across, to the right of the start's heading.
  • z: number — World units along the start's heading.

TurnRunner

interface TurnRunner

A turn run.

  • readonly run: Runner<TurnItem> — runner-core's run under it.
  • readonly state: TurnRunnerState — Where the runner is.
  • readonly options: Readonly<{ width: number; body: TurnBody; coinRadius: number }> — The options, defaults filled in.
  • input(move: TurnMove): void — A swipe or a button: 'left' and 'right' take a corner inside its window; jumps and slides need the ground.
  • steer(tilt: number): void — The tilt, -1 (full left) to 1 (full right): how fast the runner moves across.
  • step(dt: number): void — Advance dt seconds, in fixed steps of 1/120 s.
  • canTurn(): boolean — True inside a corner's turn window, before the turn is taken.
  • view(): TurnView — What is where.
  • drain(): TurnEvent[] — Events since the last call.
  • snapshot(): TurnRunnerSave — The run as plain JSON.
  • restore(save: TurnRunnerSave): void — Pick up a saved run made with the same options.
  • clone(): TurnRunner — A separate run with the same options at the same point.

TurnRunnerApi

interface TurnRunnerApi

What the turn-runner-3d pack adds to a game: game.turnRunner.

  • create: typeof createTurnRunner — Start a turn run.
  • validate: typeof validateTurnRunner — Check a turn run's options; empty when it can be run.
  • chunks: typeof templeChunks — The built-in path as chunks.
  • powerUps: typeof turnRunnerPowerUps — The built-in power-ups.
  • body: typeof turnBodyDefaults — The runner's body defaults.
  • autopilot: typeof createTurnAutopilot — A player that looks ahead, for an attract mode or a test.

TurnRunnerOptions

interface TurnRunnerOptions

A turn run's options: the path, the body, and runner-core's run.

  • width?: number — The path's width. Default 4.2.
  • body?: Partial<TurnBody> — The runner's body and moves.
  • chunks?: RunnerChunk<TurnItem>[] — The chunks. Default templeChunks().
  • opening?: string[] — Chunk ids played first. Default ['start'] with the built-in chunks.
  • powerUps?: Record<string, RunnerPowerUp> — The power-ups. Besides runner-core's shield, invulnerable, multiplier and speed, the motor reads data.reach (a magnet's pull) and data.auto (a boost: corners are taken and gaps crossed by themselves). Default turnRunnerPowerUps.
  • coinRadius?: number — How far from a coin the runner takes it. Default 0.8.
  • run?: Omit<RunnerOptions<TurnItem>, 'chunks' | 'opening' | 'powerUps' | 'hits'> — runner-core's options for the run.

TurnRunnerSave

interface TurnRunnerSave

A turn run saved as plain JSON.

  • run: RunnerSave — runner-core's save of the run underneath.
  • state: TurnRunnerState — The runner's state when the save was made.
  • taken: string[] — Ids of the coins and power-ups already picked up.
  • struck: string[] — Ids of the barriers already struck (and, with :side, struck from the side), so each hits once.
  • choices: [number, 'left' | 'right'][] — The turn taken at each T-junction passed, as [chunk index, direction].
  • origin: [number, number, number, number] — Where the first stretch kept starts: x, z, heading, and its chunk's index.

TurnRunnerState

interface TurnRunnerState

Where the runner is and what it is doing.

  • across: number — Across the path from its middle (negative is left).
  • y: number — Height of its feet; below 0 it is falling.
  • vy: number — Vertical speed.
  • distance: number — Distance along the path: runner-core's.
  • heading: number — Which way it runs: 0 the start's way, then a quarter turn right per 1 (0 to 3).
  • grounded: boolean — On the ground.
  • sliding: number — Seconds of slide left.
  • tilt: number — The tilt, -1 (full left) to 1.
  • committed: 'left' | 'right' | null — A turn taken at the next corner, before reaching it.
  • missed: { index: number; at: number } | null — A corner run past without turning: its chunk and where its middle is. Half a width on, the path ends.
  • falling: boolean — Falling off the path.
  • jumps: number — Jumps made.
  • slides: number — Slides made.
  • turns: number — Corners taken.

TurnStretchView

interface TurnStretchView

A stretch of path, as drawn: from from, length long, heading heading, width wide.

  • id: string — The index of its chunk in the run, with :left or :right added on a branch beyond a T-junction not yet taken.
  • from: TurnPoint — Where its middle line starts.
  • heading: number — Its heading, 0 to 3.
  • length: number — Its length along the path, in world units: its chunk's length.
  • width: number — Its width across the path, in world units.
  • end: 'straight' | 'left' | 'right' | 'both' — How it ends.
  • gaps: { at: number; length: number; left: number; right: number }[] — Holes in it, as spans along and across.
  • branch?: 'left' | 'right' — A stretch beyond a T-junction not yet taken: drawn on both branches until the runner chooses.

TurnThingView

interface TurnThingView

An obstacle, coin or pickup, as drawn.

  • id: string — Unique within a view: its chunk index and item index, such as '3:1', then : and the coin's place in a line, and :left or :right on a branch not yet taken.
  • x: number — World x of its middle, to the right of the start's heading.
  • y: number — Height of its middle above the path, in world units.
  • z: number — World z of its middle, along the start's heading.
  • heading: number — The heading of the stretch it stands on, 0 to 3.
  • across: number — Where it lies across the path from the middle line, in world units; negative is left.
  • power?: string — For a pickup, the name of the power-up it starts; unset on barriers and coins.

TurnView

interface TurnView

What is where, for a presenter. Positions are world points (x across, z along the start's heading).

  • runner: TurnRunnerState & { x: number; z: number; height: number; speed: number } — The runner.
  • stretches: TurnStretchView[] — The stretches laid.
  • barriers: TurnBarrierView[] — Barriers.
  • coins: TurnThingView[] — Coins not yet taken.
  • pickups: TurnThingView[] — Power-ups not yet taken.
  • chaser: number — How close the monkeys are, 1 on the runner's heels to 0 gone.
  • canTurn: boolean — True inside a corner's turn window.