What it does
generateTerrain builds a landscape by midpoint displacement: it repeatedly splits each segment and pushes the new
middle up or down by a shrinking amount. One number, the roughness, takes it from rolling hills to a mountain range.
Both ends sit at the base height, and with a seed, or the game's own random source, the same landscape comes back
every time.
The landscape is single-valued in x by construction, and everything else depends on that. Because no two vertices
share an x, heightAtX finds the one segment that spans any x and returns the ground height there with a binary
search, cheaply every frame. climbableX tests whether the rise between two positions is within a slope.
flattenTerrain lays an exact pad or plateau and returns where it is. craterHeightfield carves a bowl.
A general polyline will not stand that treatment: carve two overlapping craters into an arbitrary outline and the line folds back on itself, after which "the height at x" has no answer. Here a crater only ever pushes vertices down, clamped to a floor, and every function keeps the vertices sorted, so the field stays single-valued however many shells land on it.
Features
- Midpoint displacement —
generateTerrainwith a width, a base height, an amplitude, a roughness from 0 to 1, and clamps on how high and low the ground may go. - Spacing or passes — ask for a widest vertex gap with
spacing, or a number ofiterations, up to 16 passes. - Seeded — a
seedor anrng; throughgame.vecTerrainit draws from the game's random source by default, so terrain replays with the game's seed. - Height anywhere —
heightAtXby binary search,Infinityoff either end. - Landing pads —
flattenTerrainmakes the ground flat between two x positions, at a height you choose or the middle's, and returns the pad. - Slope tests —
climbableXchecks a rise against a maximum slope; downhill always passes. - Craters —
craterHeightfieldlowers the ground inside a circle to a bowl, never below a floor, optionally refining the ground under it first. - Detail on demand —
refineTerrainadds vertices in a span without changing its shape, so a crater can bite into ground generated coarsely.
Good for
- Lander games — a jagged landscape with flat pads, in the style of Lunar Lander.
- Artillery games — ground that craters under every shell and stays a clean line.
- Side-scrolling shooters — the ground and, with a second field, the ceiling of a cave, in the style of Scramble.
- Moon-buggy and driving games — a surface to sample under the wheels, with slope checks for climbing, in the style of Moon Patrol.
Make it yours
The options shape the land: width and baseY, the first displacement amplitude, the roughness that decides how
much survives each pass, iterations or a spacing, minY and maxY clamps, and a seed or an rng. A cave is two
landscapes from two calls, a ceiling with a small baseY and a floor with a large one; a vertical shaft is a landscape
generated across the height and mapped with x and y swapped, then sampled with heightAtX(shaft, y).
Two very different games from the same calls: a lunar landing on a 2,400-unit landscape with a roughness of 0.55 and
two flattened pads at different heights; and an artillery duel on gentle rolling hills where every shell calls
craterHeightfield with a refinement step, so the ground under the tanks wears away shot by shot.
A quick look
A lunar landscape with two pads, a landing check, and a crater handed back to the drawn line:
const T = game.vecTerrain;
const ground = T.generateTerrain({ width: 2400, baseY: 520, amplitude: 180, roughness: 0.55, spacing: 12, minY: 260, maxY: 700 });
const pads = [T.flattenTerrain(ground, 400, 460), T.flattenTerrain(ground, 1500, 1540, 610)];
const line = game.vector.shape(ground, { closed: false, color: '#c8d0ff' });
if (craft.y + 10 >= T.heightAtX(ground, craft.x)) { /* landed on a pad, or crashed on the rocks */ }
T.craterHeightfield(ground, shell.x, shell.y, 24, 700, { step: 4 });
line.setPoints(ground, false);
Works with
vector-2d— draws the line, and takes the changed points after a crater.vector-hit— collision against the line, through its wall segments.physics-box2d— makes the line solid ground for bodies, as a chain.thrust-craft— caves of several chains with graded contact, built on these heights.lander-missions— landing-site rules and scoring.excavation,procgenandterrain-3d— terrain dug cell by cell, seeded noise for other shapes, and the 3D counterpart.
Good to know
- One line, with no overhangs and no caves in a single field: a tunnel needs two fields or a different representation.
- Without a refinement step, a crater narrower than the vertex spacing only moves the vertices inside it, so it carves a notch or nothing.
- A crater's floor bounds how deep the crater digs, not the terrain: ground already below it is left alone.
climbableXis a two-point slope test, not a walk, so a vehicle that should stop partway up a hill has to step it itself.- The functions change the array in place, so anything built from it, a drawn shape or a physics chain, must be given the new points.






