The pack
physicsRope
function physicsRope(options: PhysicsRopeOptions = {}): Pack<{ ropes: RopeWorld }>
The physics-rope pack: game.ropes, a rope world stepped every fixed step, after physics-2d, physics-box2d
and physics-3d so a rope tied to a body sees where the body went this step. Gravity defaults to 900 units/s² down
in a 2D world and 9.81 m/s² down (y up) in a 3D one.
Functions
createRopeWorld
function createRopeWorld(options: RopeWorldOptions = {}): RopeWorld
Make a rope world. See RopeWorldOptions.
ropeContact
function contact(c: RopeCollider, x: number, y: number, z: number, r: number): Contact | null
The overlap of a ball at (x, y, z) of radius r with a shape, or null when they do not touch.
segmentsCross
function segmentsCross(p1x: number, p1y: number, p2x: number, p2y: number, q1x: number, q1y: number, q2x: number, q2y: number): boolean
Do the 2D segments p1-p2 and q1-q2 cross? Touching counts.
Classes
RopeWorld
class RopeWorld
The rope world. Make one with createRopeWorld, or compose the physics-rope pack for game.ropes.
readonly gravity: { x: number; y: number; z: number }— Gravity, live: change it whenever.constructor(options: RopeWorldOptions = {})addLoad(spec: RopeLoadSpec): RopeLoad— Add a load ropes can carry. Returns its handle.load(id: string): RopeLoad | undefined— A load by id, or undefined.removeLoad(id: string): void— Remove a load. Ropes tied to it are cut at that end.addRope(spec: RopeSpec): Rope— Make a rope between two ends. Returns its handle.rope(id: string): Rope | undefined— A rope by id, or undefined.ropes(): Rope[]— Every rope still in the world.removeRope(id: string): void— Remove a rope. Its loads stay.cutAlong(path: ReadonlyArray<RopeVec>): { rope: string; segment: number }[]— Cut every rope segment the swipe crosses, this step or the last, so a fast swipe cannot pass between frames of a thin rope. The swipe is a polyline in the xy plane. Returns what was cut.nearest(point: RopeVec, within = Infinity): { rope: string; segment: number; distance: number } | null— The nearest uncut rope segment to a point, withinwithinunits, or null.addCollider(c: RopeCollider): string— Add a static collider. Returns its id.removeCollider(id: string): boolean— Remove a collider.colliders(): RopeCollider[]— Every collider.step(dt: number): void— Advance bydtseconds of game time, in fixed steps. Call once per game step.drain(): RopeEvent[]— What happened since the last drain, oldest first.get dropped(): number— How many events were dropped because nobody drained them (pastlimits.events).diagnostics(): RopeDiagnostics— The state of the last step.snapshot(): RopeSnapshot— The whole world as plain JSON.followandlinkanchors are recorded where they are; re-attach them afterrestore.restore(snap: RopeSnapshot): void— Return to a snapshot. Throws on anything that is not one, leaving the world as it was.
Types
PhysicsRopeOptions
type PhysicsRopeOptions = RopeWorldOptions
The physics-rope options: the world's, with gravity defaulting to the composed world's convention.
Rope
interface Rope
A rope as the world holds it. Read it freely; change it through its methods.
readonly id: string— Its id.readonly radius: number— Its thickness, a radius.readonly segments: number— How many segments it has.readonly length: number— Its rest length now (after any pay-out or reel), the sum of its segments' rest lengths.readonly cuts: ReadonlyArray<boolean>— Which segments are cut.readonly removed: boolean— Has it been removed from the world?tension(segment: number): number— The pull on each segment in the last step, in force units (mass times length per second squared).points(): number[][]— The particle positions along it,[x, y, z]each, from the first end.runs(): number[][]— The uncut stretches of it as polylines,[x0, y0, z0, x1, y1, z1, …]: what to draw.cut(segment: number): void— Cut a segment (0 is next to the first end). Its momentum is kept on both sides.payOut(d: number): void— Let outdunits of rope (negative reels in), between a fifth and four times the length it was made with.attach(end: 'from' | 'to', to: RopeEnd): void— Tie an end to something else, or set it free (a point).
RopeBodyLink
interface RopeBodyLink
A rigid body a rope end is tied to, from any physics pack: the rope pulls it and it pulls the rope. Give its mass,
where it is, and how to push it; see the page for physics-2d, physics-box2d and physics-3d adapters.
readonly mass: number— The body's mass, in the same units as rope and load masses.position(): RopeVec— Where the tie point is now, in world units.push(ix: number, iy: number, iz: number): void— Apply an impulse (mass times velocity change) at the tie point.
RopeCollider
type RopeCollider = /** A circle in 2D, a sphere in 3D (give `z`). */ | { kind: 'circle'; id?: string; x: number; y: number; z?: number; radius: number; friction?: number } /** A segment with thickness: a peg, a bar, a branch. */ | { kind: 'capsule'; id?: string; ax: number; ay: number; az?: number; bx: number; by: number; bz?: number; radius: number; friction?: number } /** * A rectangle centred on (x, y), turned by `angle` radians about z. Give `depth` (and `z`) for a box in 3D; * without it the box reaches through every z. */ | { kind: 'box'; id?: string; x: number; y: number; z?: number; width: number; height: number; depth?: number; angle?: number; friction?: number } /** A convex polygon in the xy plane, its points in either winding. */ | { kind: 'polygon'; id?: string; points: ReadonlyArray<readonly [number, number]>; friction?: number } /** Thin walls along a polyline in the xy plane, closed or open, with an optional thickness. */ | { kind: 'chain'; id?: string; points: ReadonlyArray<readonly [number, number]>; closed?: boolean; radius?: number; friction?: number } /** Everything on the far side of a line (2D) or plane (3D): the points where n·p < offset are inside. */ | { kind: 'plane'; id?: string; nx: number; ny: number; nz?: number; offset: number; friction?: number }
A static shape ropes and loads collide with. friction (default 0.3) slows sliding along it, 0 is ice, 1 grips.
RopeContact
interface RopeContact
Where a ball overlaps a shape: the unit normal out of the shape and how deep it is.
nx: number— The unit normal pointing out of the shape, towards the ball: x.ny: number— The normal's y.nz: number— The normal's z (0 in 2D).depth: number— How far the ball must move along the normal to just touch.
RopeDiagnostics
interface RopeDiagnostics
What the world reports about its last step.
time: number— Simulated seconds so far.substeps: number— Substeps the last fixed step was split into.saturated: number— Fixed steps so far that needed more thanmaxSubsteps: fast motion the solver had to run short.maxStretch: number— The worst stretch of any segment beyond its rest length, as a fraction.maxTension: number— The largest segment tension.kineticEnergy: number— Kinetic energy of everything that moves.settled: boolean— True when nothing moves faster than a tenth of a radius per second.
RopeEnd
type RopeEnd = /** Hanging free, starting here. */ | RopeVec /** Fixed at a point: a hook, a nail, a ceiling. */ | { fixed: RopeVec } /** Tied to a load made with `addLoad`, which the rope then carries. */ | { load: string } /** Moving with whatever the function says each step: a rotating hook, a sliding rail, a hand. */ | { follow: () => RopeVec } /** Tied to a body of a physics pack, pulling and pulled. */ | { link: RopeBodyLink }
What a rope end is tied to.
RopeEvent
type RopeEvent = | { kind: 'cut'; rope: string; segment: number; cause: 'call' | 'swipe' | 'tear' } | { kind: 'contact'; load: string; collider: string }
Something that happened in a step, for a game to react to.
RopeLoad
interface RopeLoad
A load as the world holds it: live position and velocity.
readonly id: string— Its id.readonly x: number— Where it is, across.readonly y: number— Where it is, along y.readonly z: number— Where it is, along z (0 in 2D).readonly vx: number— How fast it is moving along x, units per second.readonly vy: number— How fast it is moving along y.readonly vz: number— How fast it is moving along z.readonly radius: number— Its radius.gravityScale: number— Its gravity multiplier; set it to make a bubble rise (negative) or float (0).impulse(ix: number, iy: number, iz?: number): void— Push it: an impulse, mass times velocity change.place(x: number, y: number, z?: number, vx?: number, vy?: number, vz?: number): void— Put it somewhere, at rest or with a velocity.
RopeLoadSpec
interface RopeLoadSpec
A load a rope can carry: Cut the Rope's candy, a crate, a hanging lamp.
id: string— A unique id.x: number— Where it starts, across.y: number— Where it starts, along y.z?: number— Where it starts, along z (3D). Default 0.radius: number— Its radius, for colliders and other loads.mass?: number— Its mass. Default 10.gravityScale?: number— Gravity multiplier: 0 floats, negative rises (a bubble). Default 1.vx?: number— Its starting velocity along x, units per second. Default 0.vy?: number— Its starting velocity along y. Default 0.vz?: number— Its starting velocity along z (3D). Default 0.
RopeSnapshot
interface RopeSnapshot
A whole world as plain JSON, from snapshot. Functions (follow, link) are not saved: re-attach them after restore.
format: 'phaser-ae-rope'— Always'phaser-ae-rope'.version: 1— The snapshot format's version, 1.time: number— Seconds simulated.accumulator: number— Time carried over to the next fixed step, seconds.saturated: number— How many steps ran short of substeps so far.particles: { x: number[]; y: number[]; z: number[]; vx: number[]; vy: number[]; vz: number[]; inv: number[]; radius: number[]; gravity: number[]; load: (string | null)[] }— Every particle, as parallel arrays: position, velocity, inverse mass, radius, gravity scale, and its load id.ropes: { id: string; particles: number[]; base: number[]; scale: number; cuts: boolean[]; radius: number; stretch: number; bend: number | null; tear: number | null; removed: boolean }[]—tearis null for a rope that never tears (JSON has no Infinity).anchors: { particle: number; kind: 'fixed' | 'follow' | 'link'; x: number; y: number; z: number }[]— Every held particle and where it was held (afolloworlinkend is restored as fixed there).colliders: RopeCollider[]— The colliders.nextId: number— The counter that names ropes made without an id.
RopeSpec
interface RopeSpec
A rope to make.
id?: string— A unique id. Default one is made.from: RopeEnd— The first end.to: RopeEnd— The second end.length?: number— The rope's rest length. Default: the distance between the ends as made, times1 + slack, so a rope made between two points hangs from them.slack?: number— Extra length beyond the distance between the ends, as a fraction. Default 0: taut. Ignored whenlengthis given.radius?: number— The thickness, a radius, in world units. Default 2 (pixel-sized 2D worlds); a 3D game in metres wants about 0.02.segments?: number— How many segments. Default: enough that each is about two radii long, which keeps colliders from slipping through.mass?: number— The rope's whole mass. Default 1. Loads are usually much heavier.stretch?: number— Stretch compliance, 0 inextensible (default 0), larger is elastic: about 1e-4 is a bungee.bend?: number— Bend compliance: how easily the rope folds. Leave it out for a rope that folds freely, as a rope or a chain does (the default): a slack rope then holds nothing up. Give one for a cord or cable that resists folding: smaller is stiffer, 0 a rod; about 0.02 suits a cord of mass 1, and a lighter rope needs a larger value to be as floppy.tear?: number— A segment pulled harder than this (force units) snaps. Default Infinity: never.
RopeVec
interface RopeVec
A position. z is 0 when left out, which is every 2D game.
x: number— Across.y: number— Down in a 2D game (y down), up in a 3D one (y up).z?: number— Depth, 3D only. Default 0.
RopeWorldOptions
interface RopeWorldOptions
How a rope world behaves.
gravity?: RopeVec— Gravity, units per second squared. Default{ x: 0, y: 900 }: a 2D world, y down. A 3D world in metres wants{ x: 0, y: -9.81, z: 0 }.step?: number— Fixed step, seconds. Default 1/120.iterations?: number— Constraint passes per substep. Default 8; more is stiffer and costs more.maxSubsteps?: number— The most substeps one fixed step may take. Default 16.damping?: number— Velocity damping per second (air). Default 0.2.ropeContact?: boolean— Do ropes collide with each other and with loads? Default false (Cut the Rope's ropes pass through each other).flat?: boolean— Keep everything in the z = 0 plane. Default true unless gravity has a z.limits?: { particles?: number; ropes?: number; colliders?: number; events?: number }— Resource bounds, so a runaway level fails loudly: particles (default 8192), ropes (512), colliders (1024), events kept (256).


