Wire Loop, and levels as SVG paths
I spent June working on a new mini game: Wire Loop. It's a buzz wire game - the one at carnivals and science museums where you guide a metal loop along a bent wire without touching it. Steady hand, hold your breath, and if you graze the wire it buzzes and you lose a life. It's something simple and fun for kids to play, not too cerebral (unlike the last few games).
It ticks some boxes I've not yet really explored. The mechanic is dead simple: drag the loop from the green start to the gold end. A five-year-old understands it instantly - no tutorial needed. It's also challenging, it's got that one more go pull, because failure is always feels like something you did wrong, and if you could just get better, then you'd succeed. Simple effective game loop.
Crucially for me, it's endlessly iterable. I can add levels forever, each one a slightly meaner bend than the last, and I can pour time into juice: sparks, screen flash, a buzzer sound, a gold pulse marching along the wire to show you the path. Good practice for making a game that actually feels like it could live on an app store.
Of course I couldn't resist in making it a programming challenge. The piece I'm
most pleased with is how levels are authored. All levels are loaded in via an
svg file, and each <path> in the svg represents a level. That's it. The wire
you trace is literally the d attribute of a path element.
I started with the first level, the simplest thing imaginable, a straight line:
<path d="M 10,50 H 90" />
The next one bows into a single arc, then a double S-curve, then sharp zig-zags, then a tight loop-the-loop:
<!-- level 2: one gentle arc -->
<path d="M 11.331,49.834 C 32.697,15.9 69.917,18.248 90,50" />
<!-- level 3: a double curve -->
<path d="M 10,50 C 24,80 36,80 50,50 64,20 76,20 90,50" />
<!-- level 4: sharp zig-zag -->
<path d="M 10,50 30,18 50,82 70,18 90,82" />
<!-- level 5: a tight loop -->
<path d="M 10,50 H 40 C 55,50 55,32 45,32 35,32 35,50 50,50 H 90" />
The whole difficulty curve is just me drawing progressively nastier paths in
Inkscape. No code changes to add a level. Reordering the difficulty curve is as
simple as re-ordering the SVG nodes - dragging one group above another. I also
don't have to do any curve maths. The gameplay needs to know, for any point in
time, where along the wire the loop should be, and how close the player's cursor
is to the centreline. That's a lot of bezier evaluation... except the browser
already ships a bezier engine behind getPointAtLength and getTotalLength.
So I parse the SVG, drop the paths into an off-screen document so they have real geometry, and sample them:
const doc = new DOMParser().parseFromString(text, "image/svg+xml");
const svg = doc.querySelector("svg");
// Paths need to be in a rendered document to expose geometry.
svg.style.cssText = "position:absolute;width:0;height:0;opacity:0";
document.body.append(svg);
const path = svg.querySelector("path");
const len = path.getTotalLength();
// Sample the wire into normalised 0..1 points -- no curve math here.
const norm = (count) => {
const pts = [];
for (let k = 0; k <= count; k++) {
const pt = path.getPointAtLength((k / count) * len);
pts.push({ x: pt.x / 100, y: pt.y / 100 });
}
return pts;
};
Any bezier, arc, or polyline Inkscape can draw "just works", because the
sampling is the browser's own path implementation. Levels are easy to iterate
on, and stroke-width does double duty too: it's the corridor tolerance and the
hoop radius. A wider stroke is a more forgiving level. So the one number that
makes a level look easier also makes it play easier, which is a nice bit of the
medium matching the mechanic.
Because a level is a self-contained bit of SVG, some really nice features fall
out of this, almost for free. Editing levels in Inkscape was fine but it was
a few hours work to add a level editor. Drawing a path in the browser, then
serialising it back to a <path> was straightforward, then base64-encoding
those to make shareable levels was trivial. Edit a level, copy the link, send it
to someone, and they play your level. Of course this then enables me to
trivially (and shamelessly) steal the best levels and incorporate them back into
the game!
This is exactly the kind of lesson I want to carry back to the RTS. Not the SVG specifically, but the shape of it: make level data a first-class artefact that tools and gameplay both consume, and pick a representation that makes authoring cheap. The faster it is to make a level, the more levels get made, the more you can iterate on feel.
Go play it, and if you make a nasty level with the editor, send me the link.

