What it does
You make a game of a level with game.cutRope.create(level), step it in a fixed step, and pass it the player's swipes
and taps. swipe(path) cuts every rope the finger's path crosses, tested against this step's ropes and the last's, so
a fast slash cannot pass between frames; tap(point) pops a bubble, puffs an air cushion or flips gravity at a switch.
The game tells you what happened as a list of events (a cut, a star taken, a timed star gone, a rope tied by a pin, a
candy eaten, a level won with its stars) and view() says where everything is, so your game draws it in any 2D style.
Underneath, each level runs on a rope world of its own from physics-rope, so ropes keep their swing, candies are
loads with weight, and a restart or a new level starts clean. The rules on top are the genre's: a mouth eats the candy
it wants and opens as that candy comes near, stars can run on a timer, rope pins tie a new rope when a candy passes,
bubbles float a candy away from gravity until it is tapped, cushions blow it with an impulse, switches turn the level
upside down, and spikes and the edges of the play area lose it.
A level is data, so its size and contents are yours: any number of candies, mouths for any candy or for one in
particular, hooks that stand still, slide along a path or orbit, and levels taller or wider than the screen.
validate lists every problem with a level as sentences, and snapshot and restore save a game as plain JSON.
Features
- Swipe cutting — a polyline cuts every rope it crosses, checked against two steps so thin ropes and fast swipes still meet.
- Real ropes — ropes with weight and swing from
physics-rope, on a world of each level's own. - Moving hooks — still, along a path (back and forth or looping), or orbiting, on the level's clock.
- The genre's elements — mouths, timed and untimed stars, rope pins, bubbles, air cushions, gravity switches, spike hazards and solid walls with friction.
- Several candies and mouths — each mouth can eat any candy or one in particular.
- Levels as data — any size, checked by
validate, with a default for every element's size and strength. - Elements of your own — register a kind, such as a teleporting hat or a fan, with its own state, step, tap and view; its state saves with the game.
- Events and a view — everything that happened since the last
drain(), and everything to draw, in level units. - Saves —
snapshotandrestoreas plain JSON; a save of another level is refused. - Preset levels — eight portrait levels that introduce one element at a time, and a tower 2400 units tall, each won with every star by a tested solution.
Good for
- Rope-cutting puzzles in the style of Cut the Rope, with stars to collect and a ladder of levels.
- Delivery puzzles — get a parcel, a key or a pet to its goal by cutting what holds it.
- Crane and rescue games — a load on ropes, cut free in the right order to land it safely.
- Tall scrolling levels — a level several screens high with more than one candy and mouth.
- Puzzle packs with a twist of your own — new element kinds registered by the game, with saves that keep them.
Make it yours
Everything is per level or in create's options. A level sets its size, its gravity and how far a candy may stray off
the play area; every candy's radius and mass; every rope's hook, candy, length or slack and thickness; and every mouth,
star, pin, bubble, cushion, switch, hazard and wall, each with defaults you can override, such as a bubble's rise speed
or a cushion's strength, reach and spread. create's options register element kinds by name and pass settings, such as
iterations and step, to the rope world.
Two different uses: a classic portrait level of 640 by 960 with one candy on two ropes, a mouth and two stars, one of them gone after three seconds; and a tower 720 by 2400 that scrolls, with two candies for two mouths, an orbiting hook, a rope pin and spikes, plus a teleporting element the game registered itself.
A quick look
A level played with a pointer: tap, swipe, step and listen:
const play = game.cutRope.create(game.cutRope.levels.classic[0]!);
let last: { x: number; y: number } | null = null;
game.step('cut-rope', dt => {
const p = game.input.pointer;
const at = p ? game.camera.toWorld(p.x, p.y) : null;
if (p?.pressed && at) play.tap(at); // pop a bubble, puff a cushion, flip gravity
if (p?.down && at && last) play.swipe([last, at]); // cut what the finger crosses
last = p?.down && at ? at : null;
play.step(dt);
for (const e of play.drain()) if (e.kind === 'star') game.sound.play('star');
});
Works with
physics-rope— the rope physics each level plays on; reach for it directly for ropes under rules of your own.rope-untangle— for rope puzzles about crossings rather than cutting.ninja-rope-2d— for a grappling line a character swings on, wrapping round corners.pull-pin— a physics puzzle of pins pulled rather than ropes cut.
Good to know
- Candies are loads on ropes, not rigid bodies: they do not spin, and two candies push each other apart as circles.
- Rope ends tie to hooks and candies. To tie one to a body of a physics pack, use the level's rope world,
play.world, directly; a restart or restore replaces that world. - Swipes cut in the plane of the level, and a candy floating in a bubble is still held by its ropes.
- The built-in levels are made for their screens: scale the view, not the level.
- The pack draws nothing: your game presents the view, in any art style.






