Skip to content

@bendyline/molen-pathfinding ​

Molen pathfinding: grid flow fields for many-unit (RTS) movement.

ts
import { /* … */ } from '@bendyline/molen-pathfinding';

Classes ​

FlowField ​

A flow field: per-cell cost-to-goal and a unit direction toward the goal.

Constructors ​

Constructor ​
ts
new FlowField(
   grid, 
   cost, 
   dirX, 
   dirZ
): FlowField;
Parameters ​
grid ​

Grid

cost ​

Float32Array

dirX ​

Float32Array

dirZ ​

Float32Array

Returns ​

FlowField

Properties ​

cost ​
ts
readonly cost: Float32Array;
dirX ​
ts
readonly dirX: Float32Array;
dirZ ​
ts
readonly dirZ: Float32Array;

Methods ​

directionAt() ​
ts
directionAt(x, z): [number, number];

Direction toward the goal at a world position (zero if blocked/unreachable).

Parameters ​
x ​

number

z ​

number

Returns ​

[number, number]

reachable() ​
ts
reachable(cx, cz): boolean;
Parameters ​
cx ​

number

cz ​

number

Returns ​

boolean


Grid ​

A uniform grid mapping world XZ to cells, with per-cell blocked flags.

Cell count is capped (GridOptions.maxCells, default DEFAULT_MAX_CELLS) because the grid itself is the cheap part: the Uint8Array of blocked flags is 1 byte per cell, while each flow-field query over it costs about 13 bytes per cell and a full Dijkstra sweep.

Constructors ​

Constructor ​
ts
new Grid(opts): Grid;
Parameters ​
opts ​

GridOptions

Returns ​

Grid

Properties ​

cellSize ​
ts
readonly cellSize: number;
cols ​
ts
readonly cols: number;
maxCells ​
ts
readonly maxCells: number;

The cell-count ceiling this grid was built under (see GridOptions.maxCells).

origin ​
ts
readonly origin: [number, number];
rows ​
ts
readonly rows: number;

Methods ​

cellToWorld() ​
ts
cellToWorld(cx, cz): [number, number];

Cell center in world XZ.

Parameters ​
cx ​

number

cz ​

number

Returns ​

[number, number]

inBounds() ​
ts
inBounds(cx, cz): boolean;
Parameters ​
cx ​

number

cz ​

number

Returns ​

boolean

index() ​
ts
index(cx, cz): number;
Parameters ​
cx ​

number

cz ​

number

Returns ​

number

isBlocked() ​
ts
isBlocked(cx, cz): boolean;
Parameters ​
cx ​

number

cz ​

number

Returns ​

boolean

setBlocked() ​
ts
setBlocked(
   cx, 
   cz, 
   value?
): void;
Parameters ​
cx ​

number

cz ​

number

value? ​

boolean

Returns ​

void

worldToCell() ​
ts
worldToCell(x, z): [number, number];

World XZ → cell coordinates (floored).

Parameters ​
x ​

number

z ​

number

Returns ​

[number, number]

Interfaces ​

GridOptions ​

Properties ​

cellSize ​
ts
cellSize: number;

World size of one cell (square).

cols ​
ts
cols: number;
maxCells? ​
ts
optional maxCells?: number;

Opt-in ceiling on cols * rows (default DEFAULT_MAX_CELLS = 4,000,000). Raise it only after measuring: every computeFlowField call costs about 13 bytes per cell and a full Dijkstra sweep over the grid, so a 10,000x10,000 grid is ~1.3 GB and minutes of blocked worker per query. Prefer a coarser cellSize over a bigger grid.

origin? ​
ts
optional origin?: [number, number];

World XZ of the (0,0) cell's corner.

rows ​
ts
rows: number;

Variables ​

DEFAULT_MAX_CELLS ​

ts
const DEFAULT_MAX_CELLS: 4000000 = 4e6;

Default ceiling on cols * rows (a 2000x2000 grid). Sized off the per-query cost, not off what fits in memory: one computeFlowField allocates three Float32Arrays over every cell (plus heap entries) — about 13 bytes per cell — and runs a full Dijkstra sweep, so 4M cells is roughly 52 MB and a couple of seconds per query on a worker thread.

Functions ​

computeFlowField() ​

ts
function computeFlowField(grid, goal): FlowField;

Compute a flow field over the grid toward a goal world position (Dijkstra integration).

Cost scales with the whole grid, not with the distance walked: three Float32Arrays over every cell plus heap entries — about 13 bytes per cell — and one Dijkstra sweep of every passable cell. Budget roughly 12 MB and ~1 s per query per million cells, and reuse one field for every agent heading to the same goal (that is the point of a flow field).

Parameters ​

grid ​

Grid

goal ​

[number, number]

Returns ​

FlowField

37 guides · 36 schema formats · 41 API entry points · 10 samples. API, CLI and schema pages are generated from the shipped build.