What it does
A rope is a strand of particles with mass, held by XPBD stretch and bend constraints. That is the model a rope game needs: the rope keeps its swing when the thing on it moves, drapes over pegs and boxes with friction, stays its length or stretches like a bungee as you choose, and tears past a tension you set. An inextensible rope is also held by long-range tethers to its held ends, so a heavy load on a light rope does not stretch it.
You add ropes and loads to a RopeWorld: game.ropes when the pack is composed, or one of your own from
createRopeWorld. Each end ties to a free point, a fixed point, a load (with its own radius, mass and gravity scale,
so a bubble can lift it), a point that follows a function (a rotating hook, a trolley), or a rigid body in another
physics pack, through a link that reads where the body is and pushes it with impulses. Static colliders, from
circles and capsules to polygons, chains of walls and planes, stop ropes and loads with Coulomb friction.
Cutting is the rope game's verb: cutAlong(path) cuts every segment a polyline crosses, tested against this step's
positions and the last's, so a fast slash cannot slip between two frames of a thin rope. Each step is split into as
many substeps as the fastest particle needs rather than capping its speed, and diagnostics() says when that ran
short. The world draws nothing: runs() gives the uncut stretches of each rope as polylines to draw.
Features
- Real rope behaviour — swing, drape, stiffness from
bend, give fromstretch, and ateartension. - Ends of every kind — free,
fixed, aload, a movingfollowpoint, or alinkto a rigid body. - Loads — radius, mass and a live gravity scale, with
impulseandplace, for candies, crates and buckets. - Colliders — circles (spheres in 3D), capsules, boxes, convex polygons, chains and planes, each with friction.
- Swipe cutting —
cutAlongacross two steps,cut(segment), andnearestfor pressing on a rope. - Winches —
payOutlets a rope out or reels it in, andattachmoves an end. - Events — cuts, by call, swipe or tear, and a load's first contact with a collider.
- Diagnostics — substeps, saturated steps, the largest stretch and tension, kinetic energy and whether it has settled.
- Saves —
snapshotandrestorethe whole world as plain JSON. - 2D or 3D — flat in the z = 0 plane with gravity of 900 down in a 2D world, all three axes with 9.81 down in 3D.
- Rope contact — optionally, ropes collide with each other and with loads, for tangles and draping.
Good for
- Rope-cutting puzzles in the style of Cut the Rope, where a candy hangs on several ropes.
- Cranes, winches and tow lines — a rope from a moving trolley to a crate body, paid out and reeled in.
- Rope bridges — a rope between two fixed points, with planks along it.
- Hanging scenery — lamps, vines and chains that sway and react to the player.
- Bungees and swings — elastic ropes that stretch further under heavier loads.
- 3D games — ropes in all three axes, tied to
physics-3dbodies.
Make it yours
The world's options are gravity, step (1/120 second), iterations (8 passes a substep), maxSubsteps (16),
damping (0.2 a second), ropeContact (off), flat, and limits on particles, ropes, colliders and events (8192,
512, 1024 and 256), which make a runaway level fail loudly rather than grind. Every rope chooses its length or slack,
radius, segment count, mass, stretch and bend compliance and tear tension.
Two different uses: a candy on two inextensible ropes from fixed hooks, cut by swipes, its gravity scale turned
negative for a bubble and impulses for air cushions; and a 3D crane whose rope follows a moving trolley and links to a
crate in physics-3d, let out and reeled in with payOut.
A quick look
A load on two ropes, cut by a swipe, lifted, puffed and drawn:
const candy = game.ropes.addLoad({ id: 'candy', x: 240, y: 300, radius: 18, mass: 10 });
for (const [id, x] of [['left', 120], ['right', 360]] as const)
game.ropes.addRope({ id, from: { fixed: { x, y: 100 } }, to: { load: 'candy' }, radius: 3, slack: 0.1 });
game.ropes.cutAlong(swipePoints); // cut what the swipe crossed, this step or the last
candy.gravityScale = -0.3; // a bubble lifts it
candy.impulse(400, -200); // an air cushion puffs it
for (const e of game.ropes.drain()) if (e.kind === 'cut') playSnip();
for (const r of game.ropes.ropes()) for (const run of r.runs()) drawLine(run); // [x0, y0, z0, x1, …]
Works with
physics-2d,physics-box2dandphysics-3d— rigid bodies a rope end can be tied to; ropes step after them.cut-rope— the complete rules of a rope-cutting puzzle, built on this pack.rope-untangle— untangling puzzles, which use these ropes for feel.rope-swing— a weightless grappling rope for a body to swing on, wrapping round corners.
Good to know
- Particles collide with colliders, not segments: keep segments about two radii long, the default, so a thin peg cannot pass between them.
payOutkeeps the particle count, so a rope can grow to four times and shrink to a fifth of the length it was made with; make a new rope for more.- A body link is coupled once per game step, so a very light body on a very heavy rope is still dominated by the rope.
- Swipes cut in the xy plane; in 3D, project the pointer's path onto it, or cut with
nearest. - After
restore, moving and linked ends come back fixed where they were; attach them again.






