Phaser AE

Platformer 2D

Free packv3.0.0-42DArcade

A manual platformer motor and seeded course generator: jumps, wall kicks, ladders, slopes and moving terrain on a real rigid-body solver. Every generated course comes with a recorded set of inputs that clears it, replayed to prove the course can be finished.

This is a Free pack. Every phaser.io account can use it in their games.

Released October 14, 2026 · updated October 19, 2026

Platformer 2D: 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

platformer2d

function platformer2d():Pack<{platformer2d:Platformer2dApi}>

Install the platformer API without choosing a renderer.

Helpers

compressPlatformReplay

function compressPlatformReplay(inputs: readonly PlatformInput[]): PlatformFrame[]

Merge consecutive identical inputs, one per step, into runs with a frame count, which replay accepts.

createPlatformer

function createPlatformer(config: PlatformConfig)

Fixed-step motor. All world changes come from inputs, making rewind an exact replay.

generatePlatformer

function generatePlatformer(options: PlatformOptions): PlatformLevel

Generates and independently replays a physical solution before returning each course.

generatePlatformWorkshop

function generatePlatformWorkshop(options: PlatformWorkshopOptions): PlatformWorkshopLevel

Feature courses and mixed courses share the same reusable motor and replay certification.

planPlatformRoute

function planPlatformRoute(config: PlatformConfig, route: readonly PlatformRouteNode[], budget = 14000)

A conservative witness controller for generated routes; failure does not prove impossibility.

planPlatformWorkshop

function planPlatformWorkshop(config: PlatformConfig, steps: PlatformWorkshopStep[], budget = 20000)

Conservative controller; only accepted candidates whose actual input replay finishes are returned.

PLATFORM_STEP

const PLATFORM_STEP: number

Simulation step in seconds: 1/60. Accumulate the renderer's delta outside the pack and call tick once per step.

platformFamilies

const platformFamilies: readonly ["meadow", "highlands", "descent", "switchback", "caverns", "machinery", "ground"]

The families of generated course: meadow, highlands, descent, switchback, caverns, machinery and ground.

platformLessons

const platformLessons: Record<PlatformMechanic, string>

A short instruction for the player, for each mechanic.

platformMechanics

const platformMechanics: readonly ["walls", "slopes", "one-way", "conveyors", "moving", "swinging", "crumbling", "timed", "springs", "traction", "crushing", "seesaws", "crates", "switches", "breakables", "crouching", "ledges", "air-jumps", "dashing", "water", "wind"]

The mechanics a workshop course can teach: walls, slopes, one-way, conveyors, moving, swinging, crumbling, timed, springs, traction, crushing, seesaws, crates, switches, breakables, crouching, ledges, air-jumps, dashing, water and wind.

platformPose

function platformPose(s: PlatformSurface, frame: number): Point

Path points are offsets from the surface origin. Dwell is at EACH waypoint.

platformProfiles

const platformProfiles: { classic: { wallJump: false; wallSlide: false; ladders: true; dropThrough: true; variableJump: true; coyoteFrames: number; bufferFrames: number; }; adventure: { wallJump: true; wallSlide: true; ladders: true; dropThrough: true; variableJump: true; coyoteFrames: number; bufferFrames: number; }; }

Ready-made ability sets: classic (ladders, drop-through, variable jumps, six frames of coyote time and jump buffering) and adventure (adds wall jumps and wall slides on surfaces that allow them).

validatePlatformConfig

function validatePlatformConfig(c: PlatformConfig): void

Check a level and throw an Error naming the first fault: a count or size out of range, a repeated id, an unknown option, a surface with two motion models, a swing not one chain length from its anchor, a trigger aimed at an unknown surface, or a physics value out of range.

Types

Ladder

type Ladder = Point & { id: string; w: number; h: number; }

A ladder centred on (x, y) of size w by h world units (each 8 to 2000), with a unique id.

LivePlatform

type LivePlatform = PlatformSurface & { angle: number; active: boolean; warning: number; hits: number; }

A surface as it is now: the configured surface with its present x, y, its angle in radians, whether it is active (solid), its warning progress (0 to 1) before it crumbles or switches off, and the hits it has left before it breaks.

PlatformAbilities

type PlatformAbilities = { … }

What the character may do. coyoteFrames and bufferFrames are the frames (0 to 12) in which a late jump press or an early one still counts; airJumps is the extra jumps in the air (0 to 3). Optional flags default to off.

  • wallJump: boolean
  • wallSlide?: boolean
  • ladders: boolean
  • dropThrough: boolean
  • variableJump: boolean
  • coyoteFrames: number
  • bufferFrames: number
  • crouch?: boolean
  • ledgeGrab?: boolean
  • airJumps?: number
  • dash?: boolean
  • swim?: boolean

PlatformConfig

type PlatformConfig = { … }

A level: its surfaces (1 to 180), ladders (up to 30), coins (up to 100), triggers and zones (up to 30 each), the start and goal points, deathY (the y below which the player is lost) and the physics: gravity (400 to 1800 units per second squared), speed (80 to 350 units per second), jumpSpeed (200 to 650 units per second), maxSlope (degrees, default 50), floorSnap (units, default 8), slideOnSlope, and the dash's dashSpeed (300 to 1000 units per second, default 600) and dashFrames (1 to 30, default 12). All positions are world units, x right and y down.

  • surfaces: PlatformSurface[]
  • ladders: Ladder[]
  • coins: Point[]
  • start: Point
  • goal: Point
  • deathY: number
  • abilities: PlatformAbilities
  • gravity: number
  • speed: number
  • jumpSpeed: number
  • triggers?: PlatformTrigger[]
  • zones?: PlatformZone[]
  • maxSlope?: number
  • floorSnap?: number
  • slideOnSlope?: boolean
  • dashSpeed?: number
  • dashFrames?: number

Platformer

type Platformer = ReturnType<typeof createPlatformer>

The simulation createPlatformer returns: state, the live surfaces, tick, reset, retry, rewind, recording and replay.

Platformer2dApi

type Platformer2dApi=typeof kit

Standalone platformer motor, authored levels and certified generation.

PlatformFamily

type PlatformFamily = typeof platformFamilies[number]

The name of a course family in platformFamilies.

PlatformFrame

type PlatformFrame = { … }

A run of identical steps in a recording: input held for frames steps (1 to 24000).

  • input: PlatformInput
  • frames: number

PlatformInput

type PlatformInput = { … }

The controls for one 1/60 s step: move and climb from -1 to 1 (climb: up is positive), jump held, drop to fall through a one-way platform, crouch, interact for buttons and dash.

  • move?: number
  • jump?: boolean
  • climb?: number
  • drop?: boolean
  • crouch?: boolean
  • interact?: boolean
  • dash?: boolean

PlatformLevel

type PlatformLevel = { … }

A generated course: the seed, the normalised parameters that reproduce it, the config, the route its witness controller follows, a solution that replays to a win, and metrics from that replay (family, rooms, frames, jumps, wall jumps, drops, climbing, lift-riding frames, branches, structural signature and the attempt that was accepted).

  • seed: number
  • parameters: Required<PlatformOptions>
  • config: PlatformConfig
  • route: PlatformRouteNode[]
  • solution: PlatformFrame[]
  • metrics: { family: PlatformFamily; rooms: number; frames: number; jumps: number; wallJumps: number; drops: number; climbed: number; ridingFrames: number; branches: number; structuralSignature: string; attempt: number; }

PlatformMechanic

type PlatformMechanic = typeof platformMechanics[number]

The name of a mechanic in platformMechanics.

PlatformMotion

type PlatformMotion = { … }

How a surface moves: a triangle-wave offset (x, y world units) or a route of waypoint offsets (path, up to 12, bounced back and forth unless loop), over period frames (120 to 2400), starting phase (0 to 1) through the cycle, with dwell frames pause at each waypoint, an activation (always, ride or signal) and the momentum on departure (full, upward or none).

  • x: number
  • y: number
  • period: number
  • phase?: number
  • path?: Point[]
  • dwell?: number
  • loop?: boolean
  • activation?: 'always' | 'ride' | 'signal'
  • departure?: 'full' | 'upward' | 'none'

PlatformOptions

type PlatformOptions = { … }

Options for generatePlatformer: an unsigned 32-bit seed, difficulty (default medium), family (default auto, which rotates by seed), profile (default classic for the ground family and adventure otherwise) and rooms (3 to 10, default by difficulty).

  • seed: number
  • difficulty?: Difficulty
  • family?: PlatformFamily | 'auto'
  • profile?: PlatformProfile
  • rooms?: number

PlatformProfile

type PlatformProfile = keyof typeof platformProfiles

The name of a built-in ability set in platformProfiles.

PlatformRouteNode

type PlatformRouteNode = { … }

One leg of a route for planPlatformRoute: the target surface id and the way to reach it (jump, ladder, drop, wall or walk), with the ladder id to climb, the landing x on a wide surface and the takeoffX at which to jump.

  • surface: string
  • kind: 'jump' | 'ladder' | 'drop' | 'wall' | 'walk'
  • ladder?: string
  • x?: number
  • takeoffX?: number

PlatformState

type PlatformState = Point & { vx: number; vy: number; frame: number; grounded: boolean; support: string | null; wall: number; ladder: string | null; coyote: number; buffer: number; jumps: number; wallJumps: number; drops: number; climbed: number; ridingFrames: number; coins: number[]; won: boolean; lost: boolean; phase: string; last: string; crouched: boolean; height: number; hanging: string | null; airJumps: number; dashes: number; dashReady: boolean; reward: number; signals: string[]; events: Record<string, number>; }

The player and the run: position, velocity (units per second) and frame, what it stands on or hangs from, counters for jumps, drops, climbing and riding, the coins collected (indices into the config's coins), won and lost, the phase (won, lost, hanging, dashing, swimming, crouching, climbing, riding, grounded, wall-slide or airborne), a last message for the player, the body height, the active signals and counts of mechanic events.

PlatformSurface

type PlatformSurface = Point & { id: string; w: number; h: number; oneWay?: boolean | 'up' | 'down' | 'left' | 'right'; hazard?: boolean; checkpoint?: boolean; wallJump?: boolean; wallSlide?: boolean; ledge?: 'left' | 'right' | 'both'; slope?: 'up' | 'down'; motion?: PlatformMotion; belt?: number; traction?: { acceleration?: number; braking?: number; speed?: number; }; swing?: { anchor: Point; length: number; kick?: number; tilt?: boolean; damping?: number; }; seesaw?: { limit: number; mass?: number; }; crate?: { mass: number; }; crumble?: { delay: number; respawn?: number; fall?: boolean; }; cycle?: { on: number; off: number; phase?: number; warning?: number; }; spring?: { x?: number; y: number; boost?: number; }; crush?: 'stop' | 'hazard'; breakable?: { from: 'below' | 'above' | 'either'; hits?: number; reward?: number; }; door?: boolean; }

A solid rectangle centred on (x, y) of size w by h world units (each 8 to 2000), with a unique id and optional behaviours: one-way, hazard, checkpoint, wall jump and slide, ledge grab, slope, motion, belt, traction, swing, seesaw, crate, crumble, cycle, spring, crush policy, breakable and door. A surface may have only one motion model (motion, swing, seesaw or crate).

PlatformTrigger

type PlatformTrigger = Point & { id: string; w: number; h: number; kind: 'button' | 'plate'; latched?: boolean; targets: { surface: string; action: 'open' | 'activate' | 'reverse'; }[]; }

A button (pressed with interact beside it) or a floor plate (pressed by the player or a crate) centred on (x, y) of size w by h world units. Its targets send open, activate or reverse to surfaces by id; a latched signal stays on, otherwise it lasts only while pressed.

PlatformWorkshopLevel

type PlatformWorkshopLevel = Omit<PlatformLevel, 'parameters'> & { parameters: Required<PlatformOptions> & { mechanic: PlatformMechanic | 'mixed'; }; mechanics: PlatformMechanic[]; lesson: string; workshopSteps: PlatformWorkshopStep[]; }

A generated workshop course: a PlatformLevel whose parameters also name the mechanic, with the mechanics it uses, its lesson text and the workshopSteps of its route.

PlatformWorkshopOptions

type PlatformWorkshopOptions = { … }

Options for generatePlatformWorkshop: an unsigned 32-bit seed, difficulty (default medium), mechanic (one mechanic, or mixed, the default) and rooms (1 to 8, default by difficulty and seed).

  • seed: number
  • difficulty?: Difficulty
  • mechanic?: PlatformMechanic | 'mixed'
  • rooms?: number

PlatformWorkshopStep

type PlatformWorkshopStep = { … }

One step of a workshop course's route: the target surface id, the landing x, the action kind to perform, an optional event counter to wait for and an optional number of frames to wait.

  • surface: string
  • x?: number
  • kind: 'push' | 'walk' | 'jump' | 'crouch' | 'use' | 'break' | 'air' | 'dash' | 'ledge' | 'swim' | 'spring' | 'wall'
  • event?: string
  • wait?: number

PlatformZone

type PlatformZone = Point & { id: string; w: number; h: number; kind: 'water' | 'wind'; xForce?: number; yForce?: number; flowX?: number; flowY?: number; }

A region of water or wind centred on (x, y) of size w by h world units, with a unique id. Wind adds xForce and yForce accelerations (units per second squared, y down); water carries with flowX and flowY; each is within -1600 to 1600.

Point

type Point = { … }

Coordinates are world units, x right and y down; times are fixed 60 Hz frames.

  • x: number
  • y: number