Phaser AE

Vector Terrain

Free packv3.0.0-32DVector

Line landscapes for 2D games: one seeded polyline you can sample for a height anywhere, flatten into landing pads and blow craters into, without it ever folding over itself.

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

Released October 14, 2026 · updated October 20, 2026

Vector Terrain: 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

vectorTerrain

function vectorTerrain(): Pack<{ vecTerrain: VecTerrainApi }>

The vector-terrain pack. Pure maths, so it needs no backend and runs headless.

Helpers

climbableX

function climbableX(terrain: readonly Vec2[], fromX: number, toX: number, maxClimbSlope: number): number

Slope-limited horizontal step along a heightfield. Returns the ALLOWED x: toX if the step's uphill slope is within maxClimbSlope (rise/run — ~1 is 45°), otherwise fromX (refused). Downhill is always allowed.

craterHeightfield

function craterHeightfield(polyline: Vec2[], cx: number, cy: number, radius: number, floorY: number, opts: CraterOptions = {}): void

Blow a crater into a heightfield polyline, in place — destructible terrain. Lowers the surface within radius of (cx, cy) following a circular bowl, ONLY ever pushing the ground down and clamping to floorY, so the surface stays single-valued and heightAtX stays valid. With step, vertices are added under the crater first so it keeps its shape however coarse the terrain is.

flattenTerrain

function flattenTerrain(polyline: Vec2[], fromX: number, toX: number, y?: number): { x0: number; x1: number; y: number }

Flatten the ground between fromX and toX to height y, IN PLACE: a landing pad, a plateau, a runway, a firing position. Vertices are added at both edges so the flat runs exactly from fromX to toX, and the vertices between are set to y, raised or lowered, so the field stays single-valued. y defaults to the ground height at the middle of the span. Returns the pad as { x0, x1, y }, clamped to the polyline's span.

generateTerrain

function generateTerrain(opts: HeightfieldOptions): Vec2[]

Midpoint-displacement terrain as a polyline, sorted left-to-right and single-valued in x, ready for heightAtX, flattenTerrain, craterHeightfield, game.vector.shape(points, { closed: false }) and vector-hit's polylineSegments. Deterministic: the same seed (or rng stream) gives the same ground. Generate once per level; never per frame.

Throws on a width that is not positive or a pass count past TERRAIN_MAX_ITERATIONS.

heightAtX

function heightAtX(polyline: readonly Vec2[], x: number): number

Sample the y of a terrain polyline at world x, linearly interpolating between the two vertices spanning x. Points must be sorted by x ascending (every function here keeps them so). A binary search, so it is cheap to call per body per frame. Returns Infinity if x is outside the polyline (treat as: no ground here).

refineTerrain

function refineTerrain(polyline: Vec2[], fromX: number, toX: number, maxSpacing: number): number

Add vertices to a terrain polyline, IN PLACE, so no segment between fromX and toX is longer than maxSpacing world units. The shape does not change (each new vertex sits on the old line); what changes is how finely a crater or a pad can then bend it. Clamped to the polyline's own span. Returns the number of vertices added. Throws on a maxSpacing that is not positive.

TERRAIN_MAX_ITERATIONS

const TERRAIN_MAX_ITERATIONS: 16

The most subdivision passes generateTerrain runs: 2^16 + 1 vertices, a bound on memory and time.

Types

CraterOptions

interface CraterOptions

Options for craterHeightfield.

  • step?: number — Refine the ground under the crater first, so no segment within it is longer than this, world units. A crater narrower than the terrain's own vertex spacing then carves a real bowl instead of a notch. Default unset: only the vertices already there move.

HeightfieldOptions

interface HeightfieldOptions

Options for generateTerrain: the span, ground level, roughness, resolution, clamps and seed of a midpoint-displacement heightfield.

  • width: number — Span on x, world units: the terrain runs 0..width. Must be positive.
  • baseY: number — Average ground height (screen y; larger = lower on screen). Both ends sit exactly here.
  • amplitude?: number — Initial vertical displacement, world units. Default baseY * 0.4.
  • roughness?: number — 0..1: how much amplitude survives each subdivision. Default 0.5; higher is more jagged.
  • iterations?: number — Subdivision passes: 2^iterations + 1 points. Default 6. Ignored when spacing is set.
  • spacing?: number — The widest gap between neighbouring vertices, world units: the fewest passes whose spacing is at most this (width / 2^n <= spacing), so the resolution follows the world rather than a pass count. Generate it finer than the smallest crater or pad. Default unset, which uses iterations.
  • minY?: number — Clamp ceiling: the highest the ground may rise (smallest y). Default 0.
  • maxY?: number — Clamp floor: the lowest the ground may sink (largest y). Default baseY * 2.
  • seed?: number — Seed for the displacement: the same seed and options give the same landscape. Default 1. Ignored when rng is given.
  • rng?: () => number — A random source returning [0, 1), such as () => game.rng.next(). Default a stream seeded by seed.

Vec2

interface Vec2

A 2D point or vector. Plain data, so anything can produce one.

  • x: number — Horizontal coordinate, in world units, increasing to the right.
  • y: number — Vertical coordinate, in world units; the 2D world is Y-down, so larger is lower on screen.

VecPt

type VecPt = Vec2

A point on a path — the same shape, named for what it is used as.

VecTerrainApi

type VecTerrainApi = typeof kit

game.vecTerrain — every function this pack carries, as one namespace. Its generateTerrain draws from game.rng when the options give neither seed nor rng, so a game's terrain replays with the game's seed.