Phaser AE

Lane crossing to home bays

Pro packv3.0.0-52DArcade

A lane-crossing game on a board you describe: hop across traffic, ride logs and diving turtles, and fill every home bay. The 1981 arcade layout is only the default preset, and every board is checked crossable before anyone plays it.

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

Lane crossing to home bays: 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

frogger

function frogger():Pack<{frogger:typeof rules}>

Lane-crossing rules over lane-control for any board: rows, lanes, platforms, bays and rule options are configurable; the classic arcade board is the default preset.

Functions

createFrogger

function createFrogger(definition: FroggerDefinition): FroggerGame

A replayable crossing over a validated definition: hops, time, next-level, undo/redo and validated saves.

froggerBonuses

function froggerBonuses(s: Pick<FroggerState, 'course' | 'time' | 'homes' | 'ladyTaken' | 'frog'>): { fly: number | null; flyKind: string | null; croc: number | null; lady: FroggerObject | null; }

The bay holding the bonus insect (and which kind), the bay holding a threat, and the escort piece while she can be picked up.

froggerDefinition

function froggerDefinition(input: FroggerOptions, attempt = 0): FroggerDefinition

Lay out and validate one candidate course (attempt 0–7 varies the seeded formation). Throws naming the bad option, row or lane.

froggerHint

function froggerHint(g: Pick<FroggerGame, 'state'>): { action: FroggerAction | null; reason: string; }

One safe action from the current state, or why none was found. Never changes the game.

froggerObjects

function froggerObjects(s: Pick<FroggerState, 'course' | 'time'>): FroggerObject[]

Derived objects and timed bonuses use the exact same lane samples as collision and carrying.

generateFrogger

function generateFrogger(o: FroggerOptions): { definition: FroggerDefinition; certificate: FroggerAction[]; complexity: { traffic: string[]; river: string[]; divers: string[]; hazards: string[]; homeOrder: number[]; }; timing: { tickMs: number; hopMs: number; turtleSurfaceMs: number; turtleWarningMs: number; turtleSubmergedMs: number; turtleRisingMs: number; provenance: string; }; }

Generate a course and its completion certificate: up to eight seeded formations are tried, and the winner is replayed independently through every bay without losing a frog. Throws naming the row that blocked every route.

layoutFrogger

function layoutFrogger(o:{seed:number;difficulty:'easy'|'medium'|'hard';level:number;turtleSurface:number;turtleUnderwater:number;board:FroggerBoard;rules:FroggerRules},attempt:number):FroggerLayout

Lay a validated board out as concrete lanes. Every seeded choice is drawn in a fixed order: per row lane its count, then each piece's kind and length, its spacing weights, offset and first diver; then level swaps, overlay lanes and the escort piece.

planFroggerHome

function planFroggerHome(game: Pick<FroggerGame, 'state'>, budget = 50000): FroggerAction[]

Bounded predictive search from the actual state; candidate hops simulate every collision tick. Throws a FroggerSearchError when no route is found.

resolveFroggerRules

function resolveFroggerRules(input:FroggerRulesInput={},base:FroggerRulesInput={}):FroggerRules

Merge rule overrides over the classic defaults and check every range. Throws naming the bad rule.

solveFrogger

function solveFrogger(d: FroggerDefinition): FroggerAction[]

Fill every bay, then independently replay the exact timed commands.

validateFrogger

function validateFrogger(d: FroggerDefinition): void

Check a complete definition, including any edited by hand. Throws on the first problem.

validateFroggerBoard

function validateFroggerBoard(board:FroggerBoard):void

Check a board design. Throws a message naming the row, lane or field at fault.

validateFroggerRules

function validateFroggerRules(r:FroggerRules):void

Check a complete rules object. Throws naming the bad rule.

Constants

froggerDefaultRules

const froggerDefaultRules: FroggerRules

Classic arcade rules.

froggerKind

const froggerKind = (kinds:Record<string,FroggerKind>,kind:string):FroggerKind|undefined=> …

Look up a kind's behaviour without inheriting object prototype names.

froggerPresets

const froggerPresets: Record<'classic'|'curb-hopper',FroggerPreset>

Ready-made designs: classic (the default board and rules) and curb-hopper. Pass one as preset, or copy and edit its board.

Types

Direction

type Direction = 'up' | 'down' | 'left' | 'right'

A one-cell hop.

Frog

type Frog = { … }

The frog: centre x in cells, row (fractional mid-hop), ride the speed it is being carried at, queued a buffered hop.

  • x: number
  • row: number
  • facing: Direction
  • hop: FrogHop | null
  • escort: boolean
  • ride: number
  • queued: Direction | null

FroggerAction

type FroggerAction = Advance | { kind: 'hop'; direction: Direction; } | { kind: 'next-level'; }

Commands: advance time, hop, or move on after a completed level.

FroggerBoard

type FroggerBoard = { … }

The playfield: any number of rows from start to home, each lane's direction, speed, pieces, gaps and divers, the bays, and timed bonuses. Plain JSON.

  • name?:string — Presenter name for the board (classic, curb-hopper).
  • width:number — Field width in cells, 4–64. Positions are piece left edges and frog centres in cells; hops are one cell.
  • start?:number — Frog start centre in cells; default the middle (width / 2).
  • rows:FroggerRow[] — 3–30 rows, bottom to top: row 0 must be safe (the start) and the top row must be home.
  • kinds?:Record<string,FroggerKind> — Behaviour of particular piece kinds (turtle parts, crocodile jaws, rideable otters).
  • hazards?:FroggerOverlay[] — Overlay hazard lanes, gated by level.
  • fly?:{kinds?:string[];period:number;active:number}|null — A bonus insect that sits in a random empty bay for active of every period seconds; kinds take turns. Absent: none.
  • homeCroc?:{kind?:string;from?:number;period:number;active:number}|null — A threat that occupies a random empty bay for the last active of every period seconds, from level from (default 1). Needs rules.hazards.
  • lady?:{lane:string;kind?:string;period:number;active:number}|null — An escort (the lady frog) riding one piece of a river lane for active of every period seconds; land on her and bring her home.
  • messages?:Partial<Record<FroggerCause,string>> — Death message overrides by cause.

FroggerCause

type FroggerCause='vehicle'|'water'|'dive'|'drift'|'miss'|'occupied'|'threat'|'bite'|'hazard'|'timeout'

Why a frog was lost: a vehicle; open water; a support that dived; carried or hopped off the side; the bank between bays; an occupied bay; a bay threat; a mouth; a hazard; the timer.

FroggerDefinition

type FroggerDefinition = { … }

A concrete, validated course: the board laid out as lane-control lanes, with every timing in milliseconds.

  • attempt: number — Layout attempt 0–7 that certified.
  • options: FroggerSettings — Settings that regenerate this course.
  • rows: { kind: FroggerRow['kind']; name: string; edges: FroggerEdges; }[] — Row kinds, names and edge policy, bottom (start) to top (home).
  • field: LaneField — Wrapping lanes.
  • road: { row: number; lane: string; }[] — Vehicle lanes by row.
  • river: { row: number; lane: string; }[] — Platform lanes by row.
  • hazards: { row: number; lane: string; }[] — Overlay hazard lanes by row.
  • kinds: Record<string, FroggerKind> — Piece kind behaviour.
  • homes: number[] — Bay centres in cells.
  • between: string — Presenter name for the bank between bays.
  • start: number — Frog start centre in cells.
  • hopMs: number — Hop milliseconds.
  • radius: number — Frog half-width in cells.
  • fly: { kinds: string[]; period: number; active: number; } | null — Bay bonus insect, milliseconds; null for none.
  • homeCroc: { kind: string; period: number; active: number; } | null — Bay threat, milliseconds; null when off or below its level.
  • lady: { lane: string; item: string; kind: string; period: number; active: number; } | null — Escort piece, milliseconds; null for none.
  • messages: Record<FroggerCause, string> — Death messages by cause; empty derives the text from the piece kind.

FroggerDive

type FroggerDive = { … }

A diving cycle in seconds. Missing values come from the turtleSurface/turtleUnderwater options and the .75 s warning and .35 s rising defaults.

  • surface?:number — Seconds surfaced and safe; default the turtleSurface option (5).
  • warning?:number — Seconds of visible warning, still safe; default .75.
  • submerged?:number — Seconds under water, giving no support (for a jaws kind: mouth open); default the turtleUnderwater option (1.1).
  • rising?:number — Seconds coming back up, still giving no support; default .35.
  • offset?:number — Seconds into the cycle at time zero; several divers in one lane are spread evenly from here. Default 0.
  • pace?:number — Runs the whole cycle faster (above 1) or slower (below 1); .25–4, default 1.

FroggerEdges

type FroggerEdges='block'|'open'

Whether a sideways hop past the field edge is refused (block) or allowed, so the frog lands or drifts off (open).

FroggerGame

type FroggerGame = Timeline<FroggerDefinition, FroggerState, FroggerAction> & { hint(): { action: FroggerAction | null; reason: string; }; }

A replayable crossing with a safe-move hint.

FroggerHomeRow

type FroggerHomeRow = { … }

The top row: bays to fill, with bank (bushes, shrubs) between them.

  • kind:'home' — Row kind.
  • name?:string — Presenter name.
  • bays:number[] — Bay centres in cells from the left edge, 1–16 of them; each must be filled once.
  • between?:string — Presenter name for the bank between bays; default bush. Landing on it loses a frog.

FroggerKind

type FroggerKind = { … }

Behaviour of a piece kind beyond its lane's role. Kinds not listed behave plainly: vehicles kill, platforms carry, hazards kill.

  • parts?:number — Identical parts drawn across one piece, e.g. 3 for a turtle trio that moves and dives as one; 1–8, presentation only. Default 1.
  • cycle?:'dive'|'jaws' — What the activity cycle means: dive (default) — submerged and rising pieces neither carry nor harm; jaws — the piece stays and its mouth is lethal only while submerged (open).
  • mouth?:{length:number;end:'front'|'back'|'left'|'right'} — A lethal end, in cells: crocodile jaws, an otter's head. front and back follow the lane's direction.
  • ride?:boolean — A hazard-lane piece the frog may ride: only its mouth is lethal, and on a river row its back carries the frog.
  • message?:string — Death message for this kind's bite or contact; default derived from the name (A snake caught you, Crocodile jaws).

FroggerLane

type FroggerLane = { … }

One lane of moving pieces: a road row's traffic, a river row's platforms or a hazard overlay.

  • id?:string — Unique lane id, a lowercase identifier of at most 24 characters. Default road-<row>, river-<row> or hazard-<n>.
  • direction:'left'|'right' — Which way the pieces travel.
  • speed:number — Cells per second at medium difficulty on level one, before difficulty and progression multipliers; 0–30. 0 holds still.
  • pieces:FroggerPiece[] — Piece templates (1–16), used in turn along the lane.
  • count?:FroggerTuned<number|[number,number]> — How many pieces (0–64); a [min, max] range picks by seed. Default one per template.
  • gap?:FroggerTuned<number> — Minimum clear cells between pieces, or between convoys; spare room is shared out by seed. Default 1.
  • group?:number — Pieces per convoy, travelling spacing apart; default 1 (no convoys).
  • spacing?:number — Clear cells between pieces inside a convoy; default the gap.
  • divers?:number|'all' — How many pieces dive, chosen by seed, or 'all'. Default 0.
  • dive?:FroggerDive — The divers' cycle.
  • swap?:{from:number;kind:string;dive?:FroggerDive} — From level from, one piece (chosen by seed) becomes kind with this cycle: the classic crocodile log. Needs rules.hazards.

FroggerLaneRow

type FroggerLaneRow = { … }

A road row (its lane's pieces are lethal vehicles) or a river row (its lane's pieces are the only footing, and carry the frog).

  • kind:'road'|'river' — Row kind.
  • name?:string — Presenter name.
  • edges?:FroggerEdges — Side edges; default block.
  • lane:FroggerLane — The row's traffic or platforms.

FroggerLayout

type FroggerLayout = { … }

A board resolved into lane-control lanes and row roles; part of a definition.

  • rows:{kind:FroggerRow['kind'];name:string;edges:FroggerEdges}[] — Row kinds, names and edge policy, bottom to top.
  • field:LaneField — Concrete wrapping lanes.
  • road:{row:number;lane:string}[] — Vehicle lanes by row.
  • river:{row:number;lane:string}[] — Platform lanes by row.
  • hazards:{row:number;lane:string}[] — Overlay hazard lanes by row.
  • kinds:Record<string,FroggerKind> — Piece kind behaviour.
  • homes:number[] — Bay centres in cells.
  • between:string — Presenter name for the bank between bays.
  • start:number — Frog start centre in cells.
  • fly:{kinds:string[];period:number;active:number}|null — Bay bonus insect, in milliseconds.
  • homeCroc:{kind:string;period:number;active:number}|null — Bay threat for this level, in milliseconds.
  • lady:{lane:string;item:string;kind:string;period:number;active:number}|null — Escort piece, in milliseconds.
  • messages:Record<FroggerCause,string> — Death messages by cause; empty means derived from the piece kind.

FroggerObject

type FroggerObject = LaneItem & { lane: string; row: number; phase: LanePhase; speed: number; role: 'vehicle' | 'platform' | 'hazard'; parts: number; }

A piece as sampled for collision, carrying and drawing: lane, row, activity phase, signed speed, role and drawn parts.

FroggerOptions

type FroggerOptions = { … }

Generation controls. Omit board, rules and preset for the classic arcade crossing.

  • seed: number — Unsigned 32-bit seed for counts, lengths, spacing and divers.
  • difficulty?: 'easy' | 'medium' | 'hard' — Speed multiplier (.8, 1, 1.13) and any per-difficulty lane counts and gaps; default medium.
  • level?: number — Starting level, 1 to rules.levels; default 1.
  • lives?: number — Frogs, 1–9; default 3.
  • seconds?: number — Timer seconds per frog, 10–300, or 0 for no timer; default 60.
  • turtleSurface?: number — Default seconds a diver stays surfaced, 3–12; default 5. Lanes may set their own.
  • turtleUnderwater?: number — Default seconds a diver stays under, .6–2; default 1.1. Lanes may set their own.
  • preset?: keyof typeof froggerPresets — A named design from froggerPresets supplying the board and rule defaults; default classic.
  • board?: FroggerBoard — The board, replacing the preset's.
  • rules?: FroggerRulesInput — Rule overrides, merged over the preset's rules.

FroggerOverlay

type FroggerOverlay = { … }

An extra lane laid over a row, such as a snake on the median or an otter in the river. Its pieces are hazards.

  • row:number — Row index it crosses: not the start row or the home row.
  • from?:number — First level it appears on; default 1. Needs rules.hazards.
  • lane:FroggerLane — Its moving pieces.

FroggerPiece

type FroggerPiece = { … }

One kind of moving piece. A lane uses its piece templates in turn: [log, lily pad] alternates them.

  • kind:string|string[] — Presenter name, a lowercase identifier (truck, log-small). Several names: each piece picks one by seed.
  • length:number|number[] — Physical length in cells. Several lengths: each piece picks one by seed; repeat a value to weight it.

FroggerPreset

type FroggerPreset = { … }

A complete design: a board and the rules that differ from the defaults.

  • board:FroggerBoard
  • rules:FroggerRulesInput

FroggerRow

type FroggerRow=FroggerSafeRow|FroggerLaneRow|FroggerHomeRow

One board row, listed bottom (start) to top (home).

FroggerRules

type FroggerRules = { … }

How a crossing plays. Every field has the classic arcade default.

  • support:'footprint'|'centre' — footprint (default): the whole frog must be on a surfaced piece. centre: only its centre point needs support.
  • drift:number — Cells the frog's footprint may ride past a side edge before the drift death; 0–2, default 0.
  • bayTolerance:number — Cells the frog's centre may land off a bay's centre and still enter it; 0–1.5, default .35.
  • vehicleInset:number — Cells trimmed from each end of every vehicle's hitbox; 0–1, default 0.
  • radius:number — Frog half-width in cells; .1–.45, default .23.
  • hopSeconds:number — Hop duration in seconds, .1–.4 in steps of .01; default .18.
  • bufferHops:boolean — A hop pressed mid-hop is queued and taken on landing; default false (rejected).
  • hopCarry:boolean — A hop from a moving platform keeps the platform's motion, so hops are relative to it; default false (hops are relative to the field).
  • timer:'attempt'|'life' — When the timer refills: attempt (default) — every new frog, after a death or a filled bay; life — only after a death.
  • homeSpeedUp:number — Fraction every lane speeds up per filled bay (compounding); 0–1, default 0.
  • levelSpeedUp:number — Fraction lanes speed up per level, cycling every levelCycle levels; 0–.5, default .065.
  • levelCycle:number — Levels in a progression cycle; 1–99, default 5.
  • levels:number — Levels in the game, 1–99, default 99. Filling every bay on the last level wins (status: 'won'); 1 makes a single-board game.
  • hazards:boolean — Level-gated hazards: lane swaps, overlay lanes and bay threats; default true.
  • extraLife:number — Score that awards one extra life; 0 for none. Default 20,000.
  • score:FroggerScore — Points awarded.

FroggerRulesInput

type FroggerRulesInput=Partial<Omit<FroggerRules,'score'>>&{score?:Partial<FroggerScore>}

Rules as a game supplies them: any subset, with score merged field by field.

FroggerSafeRow

type FroggerSafeRow = { … }

Solid ground: the start, a median, a verge. Overlay hazards may still cross it.

  • kind:'safe' — Row kind.
  • name?:string — Presenter name (curb, median).
  • edges?:FroggerEdges — Side edges; default block.

FroggerScore

type FroggerScore = { … }

Points awarded.

  • hop:number — Each safe landing; default 10.
  • forwardOnly:boolean — Award hop only for a row this frog has not reached since it last started; default false (every safe landing).
  • bay:number — Filling a bay; default 50.
  • second:number — Per whole second left on the timer when a bay fills; default 10.
  • fly:number — Collecting the bay bonus insect; default 200.
  • lady:number — Bringing the escort home; default 200.
  • clear:number — Filling every bay; default 1,000.

FroggerSearchError

type FroggerSearchError = Error & { furthest: number; stood: number; }

A search failure: the furthest row any explored route landed on, and the furthest row a frog could stay on for a hop.

FroggerSettings

type FroggerSettings = { … }

Resolved generation controls, stored in each definition so next-level and saves can regenerate it.

  • seed: number — Seed.
  • difficulty: 'easy' | 'medium' | 'hard' — Difficulty.
  • level: number — Level of this course.
  • lives: number — Starting frogs.
  • seconds: number — Timer seconds per frog; 0 for none.
  • turtleSurface: number — Default diver surface seconds.
  • turtleUnderwater: number — Default diver underwater seconds.
  • board: FroggerBoard — The board design.
  • rules: FroggerRules — Complete rules.

FroggerState

type FroggerState = { … }

Complete simulation state. best is the highest row this frog has reached; lastCause why the last frog was lost.

  • course: FroggerDefinition
  • time: number
  • remainder: number
  • remaining: number
  • frog: Frog
  • lives: number
  • score: number
  • homes: boolean[]
  • status: 'playing' | 'level-complete' | 'won' | 'game-over'
  • respawn: number
  • deaths: number
  • flies: number
  • escorts: number
  • extraLife: boolean
  • ladyTaken: number
  • message: string
  • lastDeath: string
  • lastCause: FroggerCause | ''
  • lastHome: number | null
  • best: number

FroggerTuned

type FroggerTuned<T>=T|{easy:T;medium:T;hard:T}

A value that may differ by difficulty: one value for all three, or {easy, medium, hard}.

FrogHop

type FrogHop = { … }

A hop in flight. carry is the platform speed it keeps (cells/second) and drift the cells carried so far.

  • fromX: number
  • fromRow: number
  • toX: number
  • toRow: number
  • elapsed: number
  • direction: Direction
  • carry: number
  • drift: number