Phaser AE

Shooting gallery

Pro packv3.0.0-32DArcade

The rules of a 2D gun game: a scrolling or static scene with depth, enemies driven by scripts that warn before they shoot, things to protect, quotas to meet and a map of missions to choose from. It stands on `light-gun` for the gun itself, and your game draws what it reports.

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

Shooting gallery: 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

shootingGallery

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

Install the shooting gallery API.

Helpers

createGallery

function createGallery(config: GalleryConfig): Gallery

Build a gallery.

CROSSBOW_VIEW

const CROSSBOW_VIEW: { w: number; h: number; }

Crossbow's screen: 320 x 240.

crossbowGun

function crossbowGun(): GunDef

The crossbow: single shots, unlimited bolts, one "DON'T SHOOT YOUR FRIENDS!" warning per game.

crossbowKinds

const crossbowKinds: ActorKind[]

Kinds: the friends, every zone's threats (7800 point table), barriers, treasures and the Evil Master.

crossbowPlanes

const crossbowPlanes: PlaneDef[]

Planes: the sky (screen-fixed flyers), the far scenery, the path the friends walk (last: the party's plane).

crossbowPreset

function crossbowPreset(o: CrossbowOptions = {}): GalleryConfig

Crossbow, Exidy 1983: the whole game as a gallery configuration.

crossbowStages

function crossbowStages(): StageDef[]

The eight danger zones and the Evil Master.

const GALLERY_STEP: number

The gallery's fixed step: 1/60 s.

galleryDifficulty

function galleryDifficulty(d: GalleryDifficulty): GalleryTuning

Difficulty multipliers: Arcade is the original (DIP Medium) tables.

operationWolfGun

function operationWolfGun(o: { magazines?: number; rockets?: number } = {}): GunDef

The light gun: the Uzi (30-round magazines, automatic changes, slow fire when out) and the rockets.

operationWolfItems

const operationWolfItems: ItemDef[]

Items: a magazine is 30 rounds, a rocket one rocket, a power drink 5 damage off, the Super Machine Gun 10 s.

operationWolfKinds

const operationWolfKinds: ActorKind[]

Actor kinds (sizes in pixels at scale 1).

operationWolfMapBoxes

const operationWolfMapBoxes: Record<string, { x: number; y: number; w: number; h: number }>

The operation map boxes for the Japanese free order (the six panels of the arcade's map, 3 x 2).

operationWolfPlanes

const operationWolfPlanes: PlaneDef[]

Depth planes: far, middle and near bands of the sand, the air and the river.

operationWolfPreset

function operationWolfPreset(o: OperationWolfOptions = {}): GalleryConfig

Operation Wolf, Taito 1987: the whole game as a gallery configuration.

operationWolfStages

function operationWolfStages(): StageDef[]

The six missions. Scroll directions follow the walkthrough (Roy Adams walks left on stages 1, 5 and 6).

OPWOLF_VIEW

const OPWOLF_VIEW: { w: number; h: number; }

Operation Wolf's playfield: the 240 x 240 picture left of the 80-pixel status panel.

validateGallery

function validateGallery(c: GalleryConfig): void

Validate a configuration; throws a clear error for unsupported data.

Types

Actor

interface Actor

A live actor (plain data).

  • id: string — Id (kind-n).
  • kind: string — Kind id.
  • seq: number — Spawn serial.
  • plane: number — Plane index.
  • scale: number — Size multiplier.
  • x: number — Plane-local x: world x for world actors, screen x for screen actors.
  • y: number — Screen y of the centre.
  • sx: number — Screen x of the centre (computed each step).
  • sy: number — Screen y of the centre (computed each step).
  • dir: 1 | -1 — Facing / travel direction.
  • vx: number — Velocity x, screen pixels per second.
  • vy: number — Velocity y.
  • hp: number — Hit points left.
  • hits: number — Hits taken.
  • mode: string — Current activity for presenters: move, wait, attack, down, hop, fall, descend, hover, exit, idle, fly, walk, hold.
  • step: number — Script step index.
  • stepT: number — Seconds in the current step.
  • age: number — Seconds alive.
  • hidden: boolean — Hidden actors are not drawn or hit.
  • flash: number — Seconds of attack wind-up left (flashing).
  • attackT: number — Seconds to the next automatic wind-up.
  • attacks: number — Attacks made.
  • down: number — Seconds knocked down.
  • wave: number — Wave index that spawned it (-1: stream, -2: boss, -3: rules).
  • seen: boolean — Has been on screen.
  • slow: number — Speed multiplier (a limping walker).
  • dropped: boolean — Has dropped its item.
  • script: ScriptStep[] — Script (copied).
  • z: number — Draw/hit order.
  • points: number | null — Points override.
  • flight: { x0: number; y0: number; x1: number; y1: number; t: number; travel: number; s0: number; s1: number; arc: number; target: string | null } | null — Flight for ordnance: screen start, end, seconds, elapsed, start and end scale, arc, target walker id.
  • phase: number — Current phase index of a vulnerability cycle.
  • phaseT: number — Seconds in the current phase.
  • phaseName: string — Phase name.
  • data: Record<string, number | string | boolean> — Free data (presentation and script scratch).

ActorKind

interface ActorKind

An actor kind.

  • id: string — Unique id.
  • role?: "enemy" | "vehicle" | "aircraft" | "protected" | "item" | "prop" | "projectile" | "boss" | "animal" | "barrier" | "threat" — Role for defaults and presenters.
  • w: number — Width at scale 1.
  • h: number — Height at scale 1.
  • regions?: ScreenRegion[] — Light-gun hit regions in kind units about the centre (default the whole box).
  • hp?: number — Hits to destroy (default 1); 0 cannot be destroyed (animals hop instead).
  • points?: number — Points when destroyed.
  • hitPoints?: number — Points for a hit that does not destroy.
  • quota?: string — Quota counter decremented when destroyed ('soldier', 'helicopter', 'vehicle', 'boat').
  • protected?: string — Protected kind label (the gun's penalty table key).
  • speed?: number — Default movement speed in pixels per second at scale 1.
  • anchor?: "world" | "screen" — World actors move with the scrolling ground; screen actors are fixed to the screen (aircraft, ordnance).
  • script?: ScriptStep[] — Default motion script.
  • attack?: AttackDef — Attack.
  • react?: ReactDef — Reaction to non-lethal hits.
  • drops?: DropDef — Drops.
  • item?: string — Shooting this actor collects this item.
  • walker?: WalkerDef — Protected walker.
  • lethal?: { consume?: boolean } — Touching a walker kills it (Crossbow's threats). consume removes the threat too.
  • barrier?: BarrierDef — Barrier.
  • pickup?: { points?: number } — Walkers that reach it collect it (Crossbow treasure): points.
  • phases?: PhaseDef[] — Vulnerability cycle.
  • flight?: { travel?: number; scale?: number; arc?: number } — Ordnance flight (role projectile): seconds to arrive, end scale, arc height.
  • damage?: number — Damage when ordnance arrives at the player (default 1).
  • ghost?: boolean — Shots ignore it (default false).
  • life?: number — Seconds before it is removed as escaped (default unlimited).
  • layer?: number — Draw/hit order bias within its plane (default 0).
  • data?: Record<string, number | string | boolean> — Presentation data.

AttackDef

interface AttackDef

How an actor attacks.

  • windup?: number — Seconds the actor flashes before the attack lands (Operation Wolf's warning flash). Default 1.
  • damage?: number — Damage to the player when a shot lands (hitscan). Default 1.
  • chance?: number — Chance a landed shot hurts (default 1).
  • projectile?: string — Throw or fire a projectile kind instead of a hitscan shot.
  • target?: "player" | "walker" — Who it attacks: the player (default) or the nearest walker.
  • auto?: boolean — Attack automatically on a timer while visible (default true).
  • first?: number — Seconds before the first wind-up starts (default 0.6).
  • every?: number — Seconds between attacks (default 2.5).
  • jitter?: number — Random extra fraction of every (default 0.3).
  • max?: number — Attacks before it stops attacking (default unlimited).
  • planes?: string[] — Only attack while on these planes (by id).
  • range?: number — Walker attacks: only strike a walker within this many pixels horizontally (default unlimited).

BarrierDef

interface BarrierDef

A barrier: walkers cannot pass its x while it stands.

  • fatal?: boolean — Walkers that reach it while it stands die (a crevice, lava) rather than waiting (a raised drawbridge).
  • group?: string — Group: every barrier actor of the group must fall before any opens (two ropes). Default the actor id.
  • gap?: number — Pixels before the barrier's x where walkers stop or fall (default 8).

BossDef

interface BossDef

A boss that appears when the stage's other goals are met.

  • spawn: SpawnSpec — Spawn spec.
  • banner?: string — Banner text for presenters (WARNING!! THE FINAL HELICOPTER).
  • delay?: number — Seconds of banner before it appears (default 1.5).

CrossbowOptions

interface CrossbowOptions

Options for the Crossbow preset.

  • difficulty?: GalleryDifficulty — Difficulty (default 'normal').
  • friends?: number — Friends at the start (the DIP: 2, 3, 4 or 5; default 3).
  • maxFriends?: number — Most friends (default 8).
  • seed?: number — Seed.

DropDef

interface DropDef

Items left behind when an actor is shot.

  • items: string[] — Item ids to choose from (seeded).
  • chance?: number — Chance of a drop (default 1).
  • on?: "hit" | "destroy" — When it drops: on any hit or only when destroyed (default 'hit').
  • once?: boolean — Drop at most once (default true).
  • smart?: boolean — Leave out items that would do nothing now (a power drink with no damage, rockets at the maximum). Default true.

EndingDef

interface EndingDef

The ending after the final stage.

  • counter?: string — Counter whose final value picks the bonus.
  • bonus?: number[] — Bonus by counter value (index 0 = none: with failOnZero the game ends).
  • failOnZero?: boolean — The game ends if the counter is zero (all hostages dead).
  • restore?: boolean — Restore gun ammunition to the starting stocks and clear the damage before the next loop.
  • partyBonus?: number — Bonus when every party member who entered the final stage left it alive (Crossbow 250,000).
interface Gallery

A running gallery.

  • readonly config: GalleryConfig — The configuration.
  • readonly state: GalleryState — Live state (plain data).
  • readonly gun: Gun — The light gun.
  • readonly stageDef: StageDef — The current stage definition.
  • start(): void — Begin a new game (from attract or game over).
  • tick(seconds: number, input?: GalleryInput): void — Advance by seconds in whole fixed steps.
  • step(input?: GalleryInput): void — Advance one fixed step.
  • drain(): GalleryEvent[] — Take the events since the last drain.
  • choices(): MapChoice[] — Choices on the map screen.
  • choose(id: string): boolean — Pick a map choice.
  • kind(id: string): ActorKind — Look up a kind.
  • plane(i: number): PlaneDef — A plane by index.
  • actor(id: string): Actor | undefined — An actor by id.
  • quotaLeft(counter: string): number — Quota left on a counter this stage.
  • hud(): GalleryHud — HUD summary.
  • targets(): ScreenTarget[] — The screen targets the gun sees this step (for presenters and debugging).
  • spawn(spec: SpawnSpec): Actor | null — Spawn an actor now (rules extensions, tests).
  • addScore(points: number): void — Add points.
  • snapshot(): { gallery: GalleryState; gun: GunState } — Deep copy of the state (gallery and gun).
  • restore(s: { gallery: GalleryState; gun: GunState }): void — Restore a snapshot from a gallery built from the same configuration.

GalleryConfig

interface GalleryConfig

A complete gallery configuration (plain data plus the gun definition).

  • view: { w: number; h: number } — The playfield in screen pixels (the HUD is the presenter's).
  • gun: GunDef — The light gun.
  • planes: PlaneDef[] — Depth planes.
  • kinds: ActorKind[] — Actor kinds.
  • items?: ItemDef[] — Pickups.
  • stages: StageDef[] — Stages.
  • map: MapDef — The map.
  • damage?: { max: number; perStage?: number } | null — The damage meter (Operation Wolf): game over when full.
  • party?: PartyDef | null — The party (Crossbow): game over when all are dead.
  • clearBonus?: number — Points per stage cleared.
  • ending?: EndingDef — Ending.
  • penalties?: Record<string, { damage?: number; score?: number }> — Penalty applied by the rules per protected kind: damage on the meter, score.
  • difficulty: GalleryDifficulty — Difficulty name.
  • tuning: GalleryTuning — Difficulty multipliers.
  • timing: GalleryTiming — Timings.
  • seed: number — Seed.
  • topScore?: number — High score to beat.
  • start?: { loop?: number; stage?: string; carry?: Record<string, number> } — Starting loop (0), stage (default the map's first) and carried counters (hostages already freed).
  • flags?: string[] — Flags that start set.
  • reinforce?: { flag: string; factor: number; except?: string[] } — Quota increase without a flag: { flag, factor } (Operation Wolf: enemy counts rise unless the communication setup is cleared).
  • maxActors?: number — Most actors alive (a resource bound, default 96).

GalleryDifficulty

type GalleryDifficulty = "easy" | "normal" | "arcade"

Difficulty presets: Arcade is the original tables.

GalleryEvent

type GalleryEvent = | { type: "map"; choices: string[] } | { type: "chosen"; choice: string; stage: string } | { type: "stage-start"; stage: string; name: string; number: number; loop: number } | { type: "play"; stage: string } | { type: "spawn"; actor: string; kind: string } | { type: "hit"; actor: string; kind: string; damage: number; points: number; x: number; y: number; region: string } | { type: "destroyed"; actor: string; kind: string; points: number; x: number; y: number; scale: number; by: "shot" | "blast" | "rules"; quota?: string } | { type: "knockdown"; actor: string; kind: string } | { type: "hop"; actor: string; kind: string } | { type: "drop"; actor: string; item: string } | { type: "pickup"; actor: string; item: string; x: number; y: number; points: number } | { type: "windup"; actor: string; kind: string } | { type: "enemy-fire"; actor: string; kind: string; x: number; y: number; hurt: boolean; damage: number } | { type: "launch"; actor: string; kind: string; from: string } | { type: "player-hit"; damage: number; cause: string; total: number; x: number; y: number } | { type: "protected-hit"; actor: string; kind: string; warning: boolean; fatal: boolean; x: number; y: number } | { type: "walker-killed"; actor: string; kind: string; cause: string; x: number; y: number } | { type: "arrived"; actor: string; kind: string; counter: string } | { type: "treasure"; actor: string; points: number; by: string } | { type: "barrier-open"; group: string } | { type: "escaped"; actor: string; kind: string } | { type: "phase"; actor: string; phase: string } | { type: "strike"; actor: string; target: string } | { type: "boss-warning"; banner: string } | { type: "boss"; actor: string; kind: string } | { type: "quota"; counter: string; left: number } | { type: "stage-clear"; stage: string; bonus: number; survivors: number; partyBonus: number } | { type: "party"; members: number; added: number } | { type: "ending"; good: boolean; bonus: number; counter: number } | { type: "loop"; loop: number } | { type: "game-over"; reason: string } | { type: "gun"; event: GunEvent }

Gallery events (gun events are forwarded as { type: 'gun', event }).

GalleryHud

interface GalleryHud

HUD summary for presenters.

  • quotas: Array<{ counter: string; left: number }> — Visible quota counters and what is left.
  • damage: number — Damage on the meter and its maximum (0/0 without a meter).
  • damageMax: number — Meter maximum.
  • rounds: number — Primary weapon rounds in the magazine.
  • magazines: number | null — Spare magazines (null unlimited).
  • special: number | null — Special weapon stock (null none or unlimited).
  • escort: number — Escort counter shown (hostages freed / boarded).
  • score: number — Score.
  • top: number — High score.
  • party: number — Party members (alive, including those walking).

GalleryInput

interface GalleryInput

Gallery input for one step: the gun's input (pointer, trigger, special, reload).

  • x?: number — Pointer x in playfield pixels.
  • y?: number — Pointer y in playfield pixels.
  • onScreen?: boolean — Is the gun on the screen.
  • snap?: boolean — Jump the crosshair (touch).
  • stickX?: number — Stick x -1..1 (keyboard aiming).
  • stickY?: number — Stick y -1..1.
  • trigger?: boolean — Trigger held.
  • special?: boolean — Special (rocket) held.
  • reload?: boolean — Reload held.

GalleryState

interface GalleryState

Gallery state (plain data).

  • status: GalleryStatus — Status.
  • statusT: number — Seconds in the status.
  • stage: string — Current stage id.
  • place: string — Map place (paths mode).
  • loop: number — Loop number (0 first).
  • time: number — Stage time (seconds of play).
  • scroll: number — Scroll position in pixels.
  • score: number — Score.
  • topScore: number — High score.
  • damage: number — Damage on the meter.
  • party: number — Party members alive (between stages; walkers on screen during one).
  • partyEntered: number — Members who entered the current stage.
  • partyToEnter: number — Members still to enter.
  • partyT: number — Seconds to the next member entering.
  • kills: Record<string, number> — Kill counts this stage by quota counter.
  • quotas: Record<string, number> — Quotas this stage (after reinforcement).
  • arrived: Record<string, number> — Arrivals this stage by counter.
  • lost: Record<string, number> — Protected walkers killed this stage by counter.
  • carry: Record<string, number> — Carried counters between stages (hostages freed).
  • cleared: string[] — Stages cleared (ids, this loop).
  • survived: string[] — Stages ever survived (for first-time rewards).
  • flags: string[] — Flags.
  • wave: number — Next wave index.
  • waveT: number — Seconds since the last wave started.
  • streams: Array<{ next: number; spawned: number }> — Time each stream fires next, and spawns so far.
  • boss: null | "pending" | "alive" | "dead" — Boss: null, pending (banner), alive, dead.
  • actors: Actor[] — Actors.
  • queued: Array<{ at: number; spec: SpawnSpec; wave: number; index: number }> — Spawns waiting for their delay.
  • opened: string[] — Barrier groups opened.
  • barriers: string[] — Barrier groups seen this stage.
  • tally: { bonus: number; counted: number; survivors: number; partyBonus: number } — Clear tally: bonus being counted.
  • ending: { bonus: number; counter: number; good: boolean } | null — Ending result.
  • doomed: boolean — Stage failed an escort requirement (the game ends after the stage).
  • autoT: number — Seconds before an automatic map choice.
  • serial: number — Actor serial.
  • 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.
  • stats: { kills: number; escaped: number; rescued: number; lost: number; damageTaken: number; pickups: number } — Statistics.

GalleryStatus

type GalleryStatus = "attract" | "map" | "briefing" | "playing" | "boss-warning" | "clear" | "ending" | "over"

Gallery status.

GalleryTiming

interface GalleryTiming

Timings in seconds.

  • briefing: number — Briefing before a stage.
  • clear: number — Stage clear tally.
  • ending: number — Ending screen.
  • over: number — Game over before attract.

GalleryTuning

interface GalleryTuning

Difficulty multipliers (Arcade = 1).

  • windup: number — Attack wind-up multiplier (larger is more time to shoot first).
  • attackEvery: number — Attack interval multiplier.
  • damage: number — Damage multiplier.
  • spawn: number — Stream interval multiplier (larger is fewer spawns).
  • speed: number — Actor speed multiplier.
  • flight: number — Ordnance flight time multiplier.
  • loop: number — Per loop: the wind-up and stream intervals are multiplied by this each loop (harder).

ItemDef

interface ItemDef

A pickup's effect.

  • id: string — Item id.
  • gun?: Array<{ weapon: string; rounds?: number; magazines?: number; stock?: number; boost?: { rate?: number; free?: boolean; seconds: number } }> — Ammunition and boosts for gun weapons.
  • heal?: number — Damage removed from the meter.
  • points?: number — Points.
  • party?: number — Party members added.

MapChoice

interface MapChoice

A map choice: an id to pass to choose, the stage it leads to, and the box to shoot on the map screen.

  • id: string — Choice id (go, a stage id, or a path label).
  • stage: string — Stage it leads to.
  • box: { x: number; y: number; w: number; h: number } | null — Screen box, when the map defines one.

MapDef

interface MapDef

The map: how stages follow each other.

  • mode: "sequence" | "choice" | "paths" — sequence: a fixed order; choice: pick any open stage (prerequisites); paths: coloured paths from the current place.
  • order?: string[] — Sequence order (stage ids).
  • nodes?: Array<{ stage: string; requires?: string[] }> — Choice nodes with prerequisites.
  • start?: string — Paths: the start place id.
  • edges?: Array<{ from: string; to: string; label: string }> — Paths: labelled edges between places (from may be the start).
  • final?: string — The stage whose clearing ends a loop (default the last in order).
  • then?: Record<string, string> — Stages that always follow a stage, with no map (Crossbow's Castle Hall then the Evil Master).
  • boxes?: Record<string, { x: number; y: number; w: number; h: number }> — Screen boxes to shoot on the map, by choice id (stage id, label, or 'go').
  • boxesByCount?: Record<string, Record<string, { x: number; y: number; w: number; h: number }>> — Boxes by the number of choices on offer (Crossbow's two halves or three thirds); overrides boxes.
  • auto?: number — Seconds before a choice is made automatically (default none).

OperationWolfOptions

interface OperationWolfOptions

Options for the Operation Wolf preset.

  • difficulty?: GalleryDifficulty — Difficulty (default 'normal').
  • magazines?: number — Magazines at the start (the DIP: 4, 5, 6 or 7; default 6).
  • rockets?: number — Rockets at the start (default 5).
  • order?: "english" | "japanese" — english (fixed order, the default) or japanese (choose the order; the Camp needs the Jungle, the Airport the Camp).
  • damage?: number — Damage meter cells (default 28, counted from the arcade's panel).
  • startStage?: string — Stage to start on (default the Communication Setup).
  • seed?: number — Seed.

PartyDef

interface PartyDef

A party of friends who are the lives (Crossbow).

  • start: number — Members at the start.
  • max: number — Most members.
  • kinds: string[] — Walker kinds, cycled.
  • gap: number — Seconds between members entering.
  • bonus: number — Points per survivor at the end of each stage.

PhaseDef

interface PhaseDef

A vulnerability cycle: named phases with shielded regions and an attack at the end of a phase.

  • name: string — Phase name (copied to the actor's phase for presenters).
  • t: number — Seconds.
  • shield?: string[] — Region ids that are shields during this phase.
  • strike?: boolean — Attack when the phase ends untouched (the Evil Master's red eyes).
  • breakOnHit?: boolean — Region ids hit during the phase cut it short (default false).

PlaneDef

interface PlaneDef

A depth band: where actors on it stand and how big they are.

  • id: string — Plane id.
  • ground: number — Screen y of the ground line (actors' feet) on this plane.
  • scale: number — Size multiplier for actors on this plane (1 is the kind's own size).
  • parallax?: number — Scroll factor for world-anchored actors (default 1: they move with the ground).
  • z?: number — Draw and hit order base: higher is nearer (default the plane index).

ReactDef

interface ReactDef

What happens when an actor is hit but not destroyed.

  • knockdown?: number — Knocked down for this many seconds (Operation Wolf's gray soldiers).
  • hop?: boolean — Hop into the air and run off (chickens and pigs).
  • fall?: boolean — Fall to the ground (a coconut knocked out of a tree).
  • flee?: boolean — Flee off the nearest edge.

RewardDef

interface RewardDef

Stage clear rewards.

  • heal?: number — Damage removed (on top of the global per-stage heal).
  • ammo?: Array<{ weapon: string; rounds?: number; magazines?: number; stock?: number }> — Set gun ammunition.
  • flag?: string — Set a flag (Operation Wolf's communication setup).
  • party?: number — Party members added the first time this stage is survived (Crossbow).

ScriptStep

type ScriptStep = | { move: { dx?: number; dy?: number; forward?: number; toX?: number; toY?: number; up?: number; speed?: number } } | { wait: number } | { attack: true } | { exit: "left" | "right" | "top" | "bottom" | "forward" | "back"; speed?: number } | { descend: { speed?: number; to?: number } } | { fall: { gravity?: number; bounce?: number } } | { hover: { amp?: number; period?: number; seconds?: number } } | { seek: { speed?: number; seconds?: number } } | { hide: true } | { show: true } | { turn: true } | { loop: number } | { remove: true }

One step of an actor's motion script. Distances are pixels at scale 1 (multiplied by the actor's scale).

SpawnSpec

interface SpawnSpec

Spawn one or more actors.

  • kind: string — Kind id.
  • side?: "left" | "right" | "top" | "bottom" — Enter from an edge (default 'left' unless x is set).
  • x?: number — View x as a fraction 0..1 (for side: 'top' or a fixed place: a window, a hut).
  • y?: number — Screen y (default the plane's ground minus half the height; aircraft: their script).
  • plane?: string | number — Plane id or index (default 0).
  • delay?: number — Seconds after the wave starts.
  • count?: number — How many (default 1).
  • gap?: number — Seconds between them (default 0.6).
  • spacing?: number — Pixels between them at scale 1 when gap is 0 (a group running together).
  • script?: ScriptStep[] — Script override.
  • points?: number — Points override.
  • data?: Record<string, number | string | boolean> — Data for presenters.
  • layer?: number — Draw order bias.
  • needs?: { counter: string; min: number } — Only spawn when a carried counter is at least this (the Airport's hostages freed in the Camp).
  • aim?: "walker" — Place it above a walker (where that walker will be in a second): falling rocks, stalactites, lightning.
  • safe?: number — Do not appear within this many pixels of a walker: try the other side, else wait for the next chance.

StageDef

interface StageDef

A stage (a mission, a danger zone).

  • id: string — Unique id.
  • name: string — Display name.
  • caption?: string[] — Briefing lines for presenters.
  • scroll?: { speed: number; dir?: 1 | -1 } — Horizontal scroll: pixels per second and direction (1 rightward, -1 leftward). Default static.
  • quotas?: Record<string, number> — Kill quotas by counter.
  • hiddenQuotas?: string[] — Counters not shown on the HUD (Operation Wolf's trucks).
  • waves?: WaveDef[] — Scripted waves.
  • streams?: StreamDef[] — Continuous spawners.
  • boss?: BossDef — A boss after the quotas (or the party's arrival).
  • escort?: { counter: string; min: number; carry?: boolean } — Rescue requirement: at least min arrivals of walkers counting toward counter, or the game ends after the stage.
  • party?: boolean — The party crosses this stage (Crossbow).
  • reward?: RewardDef — Clear rewards.
  • look?: Record<string, string> — Presentation strings (backdrop, colours).

StreamDef

interface StreamDef

A continuous spawner.

  • kinds: Array<SpawnSpec & { weight?: number }> — Weighted kinds.
  • every: number — Seconds between spawns.
  • jitter?: number — Random extra fraction of every (default 0.5).
  • maxAlive?: number — Most actors of this stream alive at once (default 3).
  • from?: number — Seconds into the stage before it starts (default 0).
  • until?: number — Seconds into the stage after which it stops.
  • count?: number — Total spawns (default unlimited).
  • fill?: boolean — Only after the scripted waves are done (quota fill). Default false.

WalkerDef

interface WalkerDef

A protected walker crossing the screen.

  • goal: "left" | "right" | number — Where it walks to: an edge, or a view x (fraction 0..1).
  • counter?: string — Counter incremented when it arrives ('hostages', 'party').
  • hits?: number — Hits that kill it once the gun's warnings are used (default 1).
  • slow?: number — Speed multiplier after a non-fatal hit (Crossbow's limp; default 1).
  • turnAt?: number — Turn back at this view x (fraction) instead of crossing (children who run in and out).

WaveDef

interface WaveDef

A scripted wave.

  • after?: number — Seconds after the previous wave started (default 0).
  • clear?: boolean — Wait until the hostile actors of earlier waves are gone (default true).
  • at?: number — Scroll distance (pixels) before it may start.
  • spawns: SpawnSpec[] — What to spawn.