Phaser AE

Rail route

Pro packv3.0.0-32D and 3DArcade

The shared mechanic of on-rails and first-person shooters: an authored route a camera rider flies, targets that appear at depth along it, a crosshair aim ray and a gun, enemy shots you can shoot down, and a shield counter. It draws nothing, so the same route drives a vector cockpit, a polygon space battle or a light-gun street.

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

Rail route: 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

railRoute

function railRoute(): Pack<{ railRoute: typeof api }>

Install the rail route API.

Helpers

buildPath

function buildPath(leg: LegGeometry, from: Frame): BuiltPath

Build a leg's path from its geometry and the frame it starts from.

createRail

function createRail(def: RailDef): Rail

Validate a definition and build a running rail.

frameFrom

function frameFrom(pos: Vec3, forward: Vec3, up: Vec3): Frame

Build an orthonormal frame from a forward and an approximate up.

frameToWorld

function frameToWorld(f: Frame, p: Vec3): Vec3

A point given in a frame's local axes (x right, y up, z forward) as a world point.

keyedFrame

function keyedFrame(route: Frame, keys: readonly LegKey[] | undefined, s: number, pos: Vec3 = route.pos): Frame

The keyed body frame at s: the route frame turned by the keys' yaw, pitch, look-at and roll.

pathFrame

function pathFrame(path: BuiltPath, s: number): Frame

The route frame (no keys) at distance s along a built path; past either end it extends the end tangent.

rayBox

function rayBox(o: Vec3, d: Vec3, h: Vec3): number | null

Slab test of the ray o + d t against an axis-aligned box [-h, h] about the origin: entry t or null.

raySphere

function raySphere(o: Vec3, d: Vec3, c: Vec3, r: number): number | null

Distance from the ray o + d t (unit d, t >= 0) to a sphere: the entry t, or null on a miss.

splinePoints

function splinePoints(points: Vec3[], per = 16): Vec3[]

Sample a list of points into a polyline through them (centripetal Catmull-Rom, mirrored ends).

turnFrame

function turnFrame(f: Frame, yaw: number, pitch: number, roll: number): Frame

Turn a frame by yaw (right is positive), then pitch (nose up is positive), then roll (bank right is positive: the up axis leans toward the right), each about the frame's own current axes.

worldToFrame

function worldToFrame(f: Frame, p: Vec3): Vec3

A world point in a frame's local axes.

Functions

anglesOf

function anglesOf(local: Vec3): { yaw: number; pitch: number }

Yaw and pitch (radians) of a direction expressed in a frame's local axes, for turnFrame.

dirFromFrame

function dirFromFrame(f: Frame, d: Vec3): Vec3

A local direction in world axes (no translation).

dirToFrame

function dirToFrame(f: Frame, d: Vec3): Vec3

A world direction in a frame's local axes (no translation).

keyLookAt

function keyLookAt(keys: readonly LegKey[] | undefined, s: number): Vec3 | null

The latest lookAt point at or before s (or the first one ahead), if any key sets one.

keyValue

function keyValue(keys: readonly LegKey[] | undefined, field: KeyField, s: number, fallback: number): number

A keyed field at distance s: smoothstep between the surrounding keys that set it, fallback if none do.

normalize

function normalize(a: Vec3, fallback: Vec3 = { x: 0, y: 0, z: -1 }): Vec3

Unit vector (or fallback for a zero vector).

segmentHitsBox

function segmentHitsBox(a: Vec3, b: Vec3, h: Vec3, r: number): boolean

Does the segment a-b pass within r of an axis-aligned box [-h, h] about the origin?

segmentPointDistance

function segmentPointDistance(a: Vec3, b: Vec3, p: Vec3): number

Closest distance from point p to the segment a-b.

Constants

add

const add = (a: Vec3, b: Vec3): Vec3=> …

a + b.

clamp

const clamp = (n: number, lo: number, hi: number): number=> …

Clamp a number.

cross

const cross = (a: Vec3, b: Vec3): Vec3=> …

Cross product a x b.

distance

const distance = (a: Vec3, b: Vec3): number=> …

Distance between two points.

dot

const dot = (a: Vec3, b: Vec3): number=> …

Dot product.

length

const length = (a: Vec3): number=> …

Length.

lerp3

const lerp3 = (a: Vec3, b: Vec3, t: number): Vec3=> …

Linear interpolation.

madd

const madd = (a: Vec3, b: Vec3, k: number): Vec3=> …

a + b * k.

scale

const scale = (a: Vec3, k: number): Vec3=> …

a * k.

smooth

const smooth = (t: number): number=> …

Smoothstep on 0..1.

sub

const sub = (a: Vec3, b: Vec3): Vec3=> …

a - b.

vec3

const vec3 = (x = 0, y = 0, z = 0): Vec3=> …

Make a vector.

Types

Behaviour

type Behaviour = (t: RailTarget, ctx: BehaviourContext, dt: number) => void

A behaviour: edits a target each step.

BehaviourContext

interface BehaviourContext extends RailContext

Context for behaviours.

  • body: Frame — The rider's body frame (route frame, keys and pilot offset, no bank or look).
  • params: Record<string, number | string | boolean> — Behaviour parameters from the motion definition.
  • fire(t: RailTarget, projectile?: string): RailProjectile | null — Fire one of this target's projectiles now (kind default from its fire schedule).
  • remove(t: RailTarget, reason?: string): void — Remove a target with a reason (reported as expired with that reason).

BranchDef

interface BranchDef

A branch at the end of a leg.

  • options: Array<{ leg: string; when?: (ctx: RailContext) => boolean; label?: string }> — Candidate legs.
  • choose?: "first" | "random" | ((ctx: RailContext) => string) — Selection policy (default 'first' passing when); a preselection from choose() or input wins.

BuiltPath

interface BuiltPath

A leg's geometry, built once from its definition.

  • length: number — Total length in world units (0 for a stationary leg).
  • samples: PathSample[] — The arc-length table.
  • start: Frame — The frame at the start.
  • end: Frame — The frame at the end.

CameraDef

interface CameraDef

The camera the rider looks through: aim and projection share it.

  • fov?: number — Vertical field of view in radians (default 1.0).
  • aspect?: number — Width over height of the screen the aim limits assume (default 4/3).
  • near?: number — Nothing nearer than this projects (default 1).
  • aim?: { u: number; v: number; down?: number } — How far the crosshair may move, as view-plane extents |u|, |v|, and down for -v (default v); default the screen edges.

CameraPose

interface CameraPose extends Frame

The camera pose for presenters.

  • eye: Vec3 — The eye (same as pos).
  • roll: number — Roll of the view about forward relative to the route frame (bank plus keys), radians.
  • velocity: Vec3 — Rider velocity in world space.

CueDef

interface CueDef

A timed spawn on a leg, keyed to leg distance (at) or leg time (time).

  • at?: number — Fire when the rider's leg distance reaches this.
  • time?: number — Fire when the leg time reaches this (seconds).
  • spawn: SpawnSpec | SpawnSpec[] | ((ctx: RailContext) => SpawnSpec[]) — What to spawn: specs, or a function of the context returning specs.
  • every?: number — Repeat interval in the same unit (distance or seconds).
  • count?: number — How many times in all (default 1, or unlimited with every).
  • when?: (ctx: RailContext) => boolean — Skip a due firing unless this is true (it is retried next step).

FireDef

interface FireDef

A target's firing schedule.

  • projectile: string — Projectile kind id.
  • every: number — Seconds between shots.
  • first?: number — Seconds before the first shot (default a seeded fraction of every).
  • jitter?: number — Interval jitter, 0..1 of every (default 0).
  • window?: { near?: number; far?: number } — Only fire while the target's depth is in this window.
  • chance?: number — Chance each due shot is actually fired (default 1).
  • max?: number — At most this many of its projectiles alive at once (default unlimited).
  • from?: Vec3 — Fire from this local offset (default the centre).

Frame

interface Frame

An orthonormal frame: a position and the right, up and forward axes at it.

  • pos: Vec3 — The frame's origin in world space.
  • forward: Vec3 — Unit forward (the direction of travel or view).
  • up: Vec3 — Unit up.
  • right: Vec3 — Unit right, forward x up in the right-handed world.

GunDef

interface GunDef

The player's gun.

  • mode?: "ray" | "bolt" — 'ray' resolves along the aim ray (after delay); 'bolt' travels and is swept (default 'ray').
  • delay?: number — Ray mode: seconds from trigger to the first hit test (converging lasers). Default 0.
  • duration?: number — Ray mode: seconds the beam keeps testing after delay until it hits (Star Wars: 8 frames). Default 0, one test.
  • follow?: boolean — Ray mode: a lasting beam follows the current crosshair rather than the aim it was fired at. Default false.
  • speed?: number — Bolt speed, units per second (default 6000).
  • range?: number — Maximum range (default 1e6).
  • cooldown?: number — Seconds between shots (default 0.15).
  • damage?: number — Damage per hit (default 1).
  • max?: number — Shots in flight at once (default 8).
  • auto?: boolean — Holding the trigger repeats (default true); false needs a fresh press each shot.
  • replace?: boolean — A new shot ends any shot still testing (Star Wars: a press restarts the 8-frame beam). Default false.

HoldDef

interface HoldDef

Stop the rider until a condition.

  • at?: number — Leg distance to stop at (default the leg's end).
  • until?: (ctx: RailContext) => boolean — Resume when this is true.
  • cleared?: string | true — Resume when this group (or, with true, every target spawned on this leg) is gone and the cues are done.
  • time?: number — Resume after this many seconds of holding at the latest.

LegDef

interface LegDef

One leg of the route.

  • id: string — Unique id.
  • phase?: string — Free-text phase name for rules and presenters.
  • length?: number — Straight run continuing the start frame (ignored when path is set).
  • path?: PathDef — Spline path.
  • from?: string — Leg whose end frame this leg starts from (default the previous leg in the list).
  • speed?: number — Route speed, units per second (default the rail's speed).
  • keys?: LegKey[] — Keys along the leg.
  • pilot?: PilotDef — Pilot movement.
  • look?: LookDef — View turn.
  • cues?: CueDef[] — Timed spawns.
  • hold?: HoldDef — A stop.
  • next?: string | BranchDef — The next leg or a branch (default the following leg in the list; the last leg ends the route).
  • end?: boolean — The route ends at this leg even if another follows in the list.
  • keepTargets?: boolean — Keep this leg's targets when leaving it (default false: they are removed).

LegGeometry

interface LegGeometry

Minimal leg shape the path builder reads (the full LegDef lives in rail.ts).

  • length?: number — A straight run continuing the previous leg's heading, in world units.
  • path?: PathDef — A spline path.
  • keys?: LegKey[] — Keys along the leg.

LegKey

interface LegKey

A keyed value along a leg, interpolated with smoothstep between keys that set the same field.

  • at: number — Distance along the leg, in world units.
  • speed?: number — Route speed (units per second) from here.
  • roll?: number — Bank about the direction of travel, radians (positive leans the up axis right).
  • yaw?: number — View turned off the tangent, radians (positive right).
  • pitch?: number — View tilted off the tangent, radians (positive up).
  • lookAt?: Vec3 — A world point the view turns toward, weighted by lookWeight.
  • lookWeight?: number — 0..1, how far the view turns toward lookAt (default 1 where lookAt is set).

LookDef

interface LookDef

View turn from steering: the view yaws and pitches toward the steer direction.

  • yaw?: number — Yaw at full steer, radians (default 0).
  • pitch?: number — Pitch at full steer, radians (default 0).
  • rate?: number — Turn rate, radians per second (default 1.5).
  • follow?: "steer" | "aim" — 'steer' or 'aim' (default 'aim').
  • track?: (ctx: RailContext) => Vec3 | null — Auto-tracking: a world point the view turns toward at rate (unlimited angle), or null to hold. Star Wars' space phase, where R2-D2 swings the X-wing toward the current attacker. Overrides yaw/pitch while it returns a point.

MotionDef

type MotionDef = | { type: "static" } | { type: "velocity"; v: Vec3 } | { type: "path"; keys: Array<{ t: number; x: number; y: number; z: number }>; loop?: boolean } | { type: "behaviour"; id: string; params?: Record<string, number | string | boolean> }

How a target moves.

PathDef

interface PathDef

A spline path for a leg: control points the route passes through.

  • points: Vec3[] — Control points (at least one). The route passes through every point.
  • relative?: boolean — When true the points are in the previous leg's end frame (x right, y up, z forward from its end), and the leg's start point is prepended, so a relative path always continues the route. Default false (world space, used as given).
  • samples?: number — Samples per span for the arc-length table (default 16, at most 256).

PathSample

interface PathSample

One sample of a built path.

  • s: number — Distance from the leg start.
  • pos: Vec3 — Position.
  • forward: Vec3 — Unit tangent.
  • up: Vec3 — Unit up (rotation-minimising).

PickResult

interface PickResult

A hit query result.

  • what: "target" | "projectile" — 'target' or 'projectile'.
  • id: string — Its id.
  • kind: string — Kind id.
  • region: string — Region id for targets ('body' without regions).
  • distance: number — Distance along the ray.
  • at: Vec3 — World hit point.

PilotDef

interface PilotDef

Pilot movement inside a leg: the offset range is the corridor's walls.

  • x?: [number, number] — Lateral offset range [min, max] in route-frame units (default [0, 0]).
  • y?: [number, number] — Vertical offset range [min, max] (default [0, 0]).
  • mode?: "position" | "velocity" — 'position': the control picks a point in the range and the offset moves there at rate (default). 'velocity': the control sets the offset speed, rate at full deflection (the Star Wars yoke on the Death Star surface and in the trench).
  • rate?: number | [number, number] — Offset speed limit (position) or full-deflection speed (velocity), units per second; one number or [x, y] (default 400).
  • relative?: boolean — rate is a fraction of the current route speed instead of units per second (default false).
  • bank?: number — Bank in radians at full lateral speed (default 0).
  • bankLag?: number — Seconds the bank takes to follow (default 0.15).
  • follow?: "steer" | "aim" — 'steer' follows input.steer; 'aim' follows the crosshair (default 'steer').

ProjectileKind

interface ProjectileKind

A kind of enemy projectile.

  • id: string — Unique id.
  • radius?: number — Radius for hits on the rider and by shots (default 20).
  • speed: number — Speed (relative to the rider when homing), units per second.
  • damage?: number — Shield damage on reaching the rider (default 1).
  • homing?: boolean | number — true closes on the rider every step; a number is a turn rate in rad/s; false flies straight, led.
  • shootable?: boolean — Shots can destroy it (default true).
  • hp?: number — Hit points (default 1).
  • points?: number — Points reported when shot down.
  • life?: number — Seconds to live (default 12).
  • halfLife?: number — Close on the rider exponentially: the offset from the eye halves every halfLife seconds, so the projectile holds its place on screen and grows (Star Wars fireballs close 1/8 of the way per frame). Overrides speed and homing.
  • needsAim?: boolean — Damage only when it arrives inside the crosshair's reachable area (Star Wars fireballs). Default false.
  • reach?: number — Distance from the eye at which it strikes (default its radius plus the rider's radius).
  • gain?: { x?: number; y?: number; z?: number } — World-anchored drift with per-axis pulls toward the rider: each second the offset from the eye, measured in the rider's body frame (x right, y up, z ahead), shrinks by exp(-gain) on that axis, on top of the projectile's own velocity (Star Wars ground and trench guns creep in and home sideways and up). Overrides speed/homing when set.

Rail

interface Rail

A running rail.

  • readonly def: RailDef — The definition.
  • readonly state: RailState — Live state (plain data).
  • readonly leg: LegDef — The current leg definition.
  • readonly targets: readonly RailTarget[] — Alive targets.
  • readonly projectiles: readonly RailProjectile[] — Alive projectiles.
  • readonly shots: readonly RailShot[] — Shots in flight.
  • tick(seconds: number, input?: RailInput): void — Advance by seconds in fixed steps.
  • step(input?: RailInput): void — Advance one fixed step.
  • drain(): RailEvent[] — Take the events since the last drain.
  • pose(): CameraPose — The view pose (body plus bank and look).
  • body(): Frame — The body frame (no bank or look): what rider-space targets ride in.
  • toCamera(p: Vec3): Vec3 — A world point in camera space (x right, y up, z depth).
  • project(p: Vec3, view: ViewRect): { x: number; y: number; z: number } | null — A world point on a screen rect, or null behind the near plane.
  • focal(view: ViewRect): number — Focal length in screen units for a rect (vector-wire's focalLength).
  • screenToAim(sx: number, sy: number, view: ViewRect): { u: number; v: number } — Screen point to view-plane aim.
  • aimToScreen(aim: { u: number; v: number }, view: ViewRect): { x: number; y: number } — View-plane aim to a screen point.
  • aimRay(aim?: { u: number; v: number }): { origin: Vec3; dir: Vec3 } — The world ray through an aim.
  • aimLimits(): { u: number; v: number; down: number } — The aim limits |u|, v up and down.
  • legFrame(leg: string, s: number): Frame — The route frame (no keys) on a leg at distance s.
  • routePoint(leg: string, s: number, x?: number, y?: number): Vec3 — A route-space point (x right, y up at distance s on leg) in world space.
  • path(leg: string): BuiltPath — Built geometry of a leg.
  • targetFrame(t: RailTarget): Frame — A target's world frame (position and oriented axes).
  • localToWorld(t: RailTarget, p: Vec3): Vec3 — A target-local point in world space.
  • spawn(spec: SpawnSpec): RailTarget | null — Spawn a target now.
  • launch(kind: string, from: Vec3, source?: string, opts?: { vel?: Vec3 }): RailProjectile | null — Fire a projectile of a kind from a world point now; vel (world units per second) overrides its aiming.
  • remove(id: string, reason?: string): void — Remove a target (no event unless reason is given).
  • hit(id: string, damage?: number, region?: string): void — Damage a target as if shot (rules-driven hits).
  • hurt(amount: number, cause?: string): void — Damage the rider.
  • kick(amount: number, seconds: number, settle?: boolean): void — Kick the view's roll: settle jumps by amount and fades back over seconds (a surface collision); otherwise it spins by amount over seconds and stays (a hit in space).
  • setShields(n: number): void — Set the shield count.
  • addShields(n: number): void — Add shields (clamped to the maximum).
  • fire(aim?: { u: number; v: number }): RailShot | null — Fire the gun now (ignores the trigger, respects cooldown).
  • pick(aim?: { u: number; v: number }): PickResult | null — What the aim ray meets first.
  • goto(leg: string, s?: number): void — Jump to a leg.
  • choose(leg: string): void — Preselect a branch leg.
  • flag(name: string, value: number | string | boolean): void — Set a rules flag.
  • setScale(scale: Partial<RailState["scale"]>): void — Scale route speed, firing rate and projectile speed.
  • kind(id: string): TargetKind — Look up a target kind.
  • projectileKind(id: string): ProjectileKind — Look up a projectile kind.
  • target(id: string): RailTarget | undefined — A target by id.
  • snapshot(): RailState — Deep copy of the state.
  • restore(s: RailState): void — Restore a snapshot from a rail built from the same definition.
  • reset(): void — Back to the start.

RailContext

interface RailContext

Context for predicates and cue functions.

  • rail: Rail — The rail.
  • state: RailState — Its state.
  • leg: LegDef — The current leg definition.
  • flags: Record<string, number | string | boolean> — Rules flags.
  • random(): number — Seeded random in [0, 1).

RailDef

interface RailDef

The full rail definition.

  • legs: LegDef[] — Legs; the first is the start unless startLeg says otherwise.
  • startLeg?: string — Starting leg id.
  • start?: StartDef — Route start frame.
  • speed?: number — Default leg speed (default 0).
  • camera?: CameraDef — Camera.
  • rider?: RiderDef — Rider.
  • kinds?: TargetKind[] — Target kinds.
  • projectiles?: ProjectileKind[] — Projectile kinds.
  • gun?: GunDef — The gun (default a ray gun).
  • shields?: { start?: number; max?: number } — Shield counter (default 1, max = start).
  • behaviours?: Record<string, Behaviour> — Named behaviours for motion: { type: 'behaviour' }.
  • seed?: number — Seed (default 1).
  • step?: number — Fixed step in seconds (default 1/60).
  • limits?: { targets?: number; projectiles?: number } — Resource bounds (defaults 512 targets, 512 projectiles).

RailEvent

type RailEvent = | { type: "leg-enter"; leg: string; phase: string } | { type: "leg-exit"; leg: string; phase: string } | { type: "hold"; leg: string } | { type: "resume"; leg: string; held: number } | { type: "branch"; from: string; to: string } | { type: "route-end"; leg: string } | { type: "spawn"; target: string; kind: string } | { type: "refused"; what: "target" | "projectile"; kind: string } | { type: "shot"; shot: string; aim: { u: number; v: number } } | { type: "hit"; target: string; kind: string; region: string; damage: number; invulnerable: boolean; friendly: boolean; at: Vec3 } | { type: "part-destroyed"; target: string; kind: string; region: string; points: number; at: Vec3 } | { type: "destroyed"; target: string; kind: string; points: number; by: "shot" | "collision" | "rules"; at: Vec3; data: TargetData } | { type: "miss"; shot: string; at: Vec3 } | { type: "passed"; target: string; kind: string; data: TargetData } | { type: "crossed"; target: string; kind: string; local: Vec3; data: TargetData } | { type: "expired"; target: string; kind: string; reason: string; data: TargetData } | { type: "fired"; projectile: string; kind: string; from: string; at: Vec3 } | { type: "projectile-destroyed"; projectile: string; kind: string; points: number; at: Vec3 } | { type: "projectile-hit"; projectile: string; kind: string; damage: number; at: Vec3 } | { type: "projectile-expired"; projectile: string; kind: string } | { type: "collision"; target: string; kind: string; damage: number; at: Vec3 } | { type: "damage"; amount: number; cause: string; shields: number; before: number } | { type: "shields-empty" }

Events, drained by the rules pack or presenter.

RailInput

interface RailInput

Input for one step.

  • aim?: { u: number; v: number } — Crosshair as a view-plane direction (u, v, 1) in camera space.
  • steer?: { x: number; y: number } — Steering in [-1, 1] on each axis.
  • fire?: boolean — Trigger held.
  • branch?: string — Preselect a branch leg.

RailProjectile

interface RailProjectile

A live enemy projectile (world space).

  • id: string — Unique id.
  • kind: string — Kind id.
  • pos: Vec3 — World position.
  • vel: Vec3 — World velocity.
  • age: number — Seconds alive.
  • hp: number — Hit points.
  • from: string — Target that fired it, if any.
  • depth: number — Depth in front of the rider.
  • fixed: boolean — Launched with a fixed velocity: no homing, no pulls.
  • dead: boolean — Marked for removal.

RailShot

interface RailShot

A player shot in flight or awaiting its delayed hit test.

  • id: string — Unique id.
  • aim: { u: number; v: number } — Aim when fired.
  • age: number — Seconds since firing.
  • pos: Vec3 — Bolt position (world).
  • vel: Vec3 — Bolt velocity (world).
  • end: Vec3 | null — Where the shot ended, once resolved.
  • done: boolean — Resolved (hit or missed).

RailState

interface RailState

Everything that changes; plain data.

  • time: number — Seconds since reset.
  • leg: string — Current leg id.
  • s: number — Distance along the current leg.
  • legTime: number — Seconds on the current leg.
  • holding: boolean — Stopped at a hold.
  • holdTime: number — Seconds held.
  • held: boolean — The hold on this leg has been released.
  • ended: boolean — The route has ended.
  • speed: number — Current route speed (after scale).
  • rider: RiderState — Rider.
  • shields: number — Shield count.
  • targets: RailTarget[] — Targets alive.
  • projectiles: RailProjectile[] — Projectiles alive.
  • shots: RailShot[] — Shots alive.
  • cooldown: number — Gun cooldown left.
  • trigger: boolean — Trigger state last step.
  • cues: Array<{ fired: number; next: number }> — Per-cue progress on this leg: firings so far and the next trigger value.
  • branch: string | null — Preselected branch.
  • flags: Record<string, number | string | boolean> — Rules flags for predicates.
  • scale: { speed: number; fire: number; projectile: number } — Scale factors.
  • stats: { shots: number; hits: number; kills: number; projectilesShot: number; damage: number } — Counters.
  • rng: number[] — The seeded random stream's state: four words, from the kernel's rng.snapshot(). It advances in place and is saved with the state.
  • nextId: number — Next id number.

RailTarget

interface RailTarget

A live target.

  • id: string — Unique id (kind-n).
  • kind: string — Kind id.
  • space: Space — Space of pos.
  • leg: string — Route space: the leg pos.z is measured along.
  • pos: Vec3 — Position in its space (route: x right, y up, z = s along leg; rider: x right, y up, z ahead).
  • vel: Vec3 — Velocity in its space, units per second.
  • yaw: number — Yaw in its space's frame.
  • pitch: number — Pitch.
  • roll: number — Roll.
  • age: number — Seconds alive.
  • hp: number — Hit points left.
  • parts: Record<string, number> — Hit points left per destructible region.
  • exposed: boolean — Hittable this step (window and exposure).
  • depth: number — Depth in front of the rider's body frame (negative behind).
  • w: Vec3 — World position this step.
  • mode: string — Behaviour mode.
  • modeTime: number — Seconds in the current mode (reset when a behaviour changes mode).
  • data: TargetData — Rules/behaviour data.
  • group: string — Group.
  • spawnLeg: string — The leg it was spawned on.
  • fireAt: number — Next firing age.
  • collided: boolean — Already collided with the rider.
  • crossed: boolean — Already reported crossed.
  • ghost: boolean — Ignored by shots and collisions while true (a spinning, thrown Vader); rules set it.
  • hits: number — Times hit.
  • motion: MotionDef | null — Motion override.
  • dead: boolean — Marked for removal this step.

RegionDef

interface RegionDef

A sphere or box in a target's local frame (x right, y up, z forward).

  • id: string — Region id, unique within the kind.
  • shape?: "sphere" | "box" — Shape (default sphere).
  • at?: Vec3 — Centre offset in the target's local frame.
  • radius?: number — Sphere radius.
  • size?: Vec3 — Box full size.
  • hp?: number — Own hit points: the region is a destructible part.
  • points?: number — Points reported when this part is destroyed.
  • damage?: number — Damage multiplier for hits here (default 1).
  • kills?: boolean — Destroying this part destroys the target.
  • friendly?: boolean — Hits here are on a protected target (a hostage).
  • hittable?: boolean — Shots can hit this region (default true).
  • solid?: boolean — The rider can collide with this region when the kind is solid (default true).

RiderDef

interface RiderDef

The player's craft.

  • radius?: number — Collision radius, world units (default 30).
  • invulnerable?: number | ((shieldsBefore: number) => number) — Seconds of immunity after taking damage, or a function of the shield count before the hit (default 0).

RiderState

interface RiderState

The rider's pilot and view state.

  • x: number — Lateral offset in the route frame.
  • y: number — Vertical offset.
  • vx: number — Lateral offset speed.
  • vy: number — Vertical offset speed.
  • bank: number — Current bank (radians).
  • lookYaw: number — Current look yaw.
  • lookPitch: number — Current look pitch.
  • aim: { u: number; v: number } — Current aim.
  • invulnerable: number — Immunity seconds left.
  • prev: Vec3 — Eye position last step (for swept collisions).
  • roll: number — Extra view roll from kicks (radians).
  • kick: { amount: number; seconds: number; t: number; settle: boolean } | null — An active roll kick: total, seconds, elapsed, settle (decay back to zero) or spin (keep it).

Space

type Space = "world" | "route" | "rider"

Where a target's position lives.

SpawnSpec

interface SpawnSpec

A spawn order: one target of a kind, placed in a space.

  • kind: string — Kind id.
  • space?: Space — Space (default the kind's space, else 'route').
  • x?: number — Right of the frame (route/rider) or world X.
  • y?: number — Up of the frame (route/rider) or world Y.
  • z?: number — Rider space: ahead of the rider. World space: world Z.
  • s?: number — Route space: absolute distance along leg.
  • ahead?: number — Route space: distance ahead of the rider (default 0 when s is not set).
  • leg?: string — Route space: which leg (default the current one).
  • vel?: Vec3 — Initial velocity in the target's space.
  • yaw?: number — Initial yaw (radians, in the space's frame; pi faces back down the route).
  • pitch?: number — Initial pitch.
  • roll?: number — Initial roll.
  • group?: string — A group for hold.cleared and rules queries (default the kind's group).
  • data?: TargetData — Data copied onto the target.
  • mode?: string — Initial mode string for behaviours (default 'start').
  • motion?: MotionDef — Motion override for this target.

StartDef

interface StartDef

The starting frame of a route.

  • position?: Vec3 — Where the route starts (default the origin).
  • forward?: Vec3 — Initial direction of travel (default -z, into a default 3D camera's screen).
  • up?: Vec3 — Initial up (default +y).

TargetData

type TargetData = Record<string, number | string | boolean>

Plain data a rules pack may hang on a target.

TargetKind

interface TargetKind

A kind of target: enemies, scenery that can be hit or collided with, pickups.

  • id: string — Unique id.
  • space?: Space — Default space for spawns of this kind (default 'route').
  • radius?: number — Hit and collision sphere radius when there are no regions (default 40).
  • hp?: number — Hit points (default 1).
  • invulnerable?: boolean — Hits register but never damage (Vader's TIE).
  • points?: number — Points reported when destroyed.
  • hittable?: boolean — Shots can hit it (default true).
  • regions?: RegionDef[] — Hit regions and parts (default one sphere of radius).
  • solid?: boolean — The rider collides with it (towers, catwalks, asteroids).
  • collide?: { damage?: number; destroy?: boolean } — Collision outcome.
  • window?: { near?: number; far?: number } — Hittable only while its depth in front of the rider is inside this window.
  • expose?: Array<[number, number]> | { up: number; down: number; offset?: number } — Hittable only during these windows of its age: a list of [from, to], or a cycle.
  • face?: "fixed" | "velocity" | "rider" — Automatic facing for presenters (default 'fixed').
  • motion?: MotionDef — Motion (default static).
  • fire?: FireDef — Firing schedule.
  • life?: number — Seconds to live (default unlimited).
  • behind?: "remove" | "keep" — What happens when it falls behind the rider by margin (default remove with passed).
  • margin?: number — Distance behind the eye before behind applies (default the radius plus 50).
  • group?: string — Default group.
  • data?: TargetData — Data copied onto every target of the kind.
  • friendly?: boolean — The whole target is protected: hitting it is a penalty for the rules pack.
  • cross?: boolean — Report crossed with the eye in the target's local frame when the rider passes its depth (fly-between bonuses).

Vec3

interface Vec3

A point or direction in 3D, in world units.

  • x: number — X component.
  • y: number — Y component (up).
  • z: number — Z component.

ViewRect

interface ViewRect

A screen rectangle for projection helpers.

  • w: number — Width.
  • h: number — Height.