From fb56db605f0bf5613485ba48c169a78507e5f68e Mon Sep 17 00:00:00 2001 From: Daddy32 Date: Fri, 12 Dec 2025 18:25:12 +0100 Subject: [PATCH] Tighten rope links and expose render type per scene --- main.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/main.js b/main.js index 9d2b96c..bd35e3e 100644 --- a/main.js +++ b/main.js @@ -17,7 +17,14 @@ minChain: 3, palette: ["#ff595e", "#ffca3a", "#8ac926", "#1982c4", "#6a4c93"], ballRadius: 18, - link: { stiffness: 0.6, lengthScale: 0.5, damping: 0.08, lineWidth: 3 }, + link: { + stiffness: 0.85, + lengthScale: 1.05, // max stretch factor; slack below this + damping: 0.08, + lineWidth: 3, + rope: true, + renderType: "line", + }, }; const scenes = [ @@ -30,7 +37,14 @@ minChain: 3, palette: ["#ff595e", "#ffca3a", "#8ac926", "#1982c4", "#6a4c93"], ballRadius: 38, - link: { stiffness: 0.6, lengthScale: 0.5, damping: 0.08, lineWidth: 3 }, + link: { + stiffness: 0.85, + lengthScale: 1.05, + damping: 0.08, + lineWidth: 3, + rope: true, + renderType: "line", + }, }, createBodies: (w, h) => [ Bodies.rectangle(w / 2, h + 40, w, 80, { @@ -58,7 +72,14 @@ minChain: 3, palette: ["#fb7185", "#fbbf24", "#34d399", "#38bdf8"], ballRadius: 22, - link: { stiffness: 0.6, lengthScale: 1.2, damping: 0.01, lineWidth: 4 }, + link: { + stiffness: 0.6, + lengthScale: 1, + damping: 0.01, + lineWidth: 4, + rope: false, + renderType: "spring", + }, }, createBodies: (w, h) => [ Bodies.rectangle(w / 2, h + 50, w, 100, { @@ -90,7 +111,14 @@ minChain: 3, palette: ["#e879f9", "#38bdf8", "#f97316", "#22c55e"], ballRadius: 16, - link: { stiffness: 1, lengthScale: 0.85, damping: 0.15, lineWidth: 3 }, + link: { + stiffness: 1, + lengthScale: 0.85, + damping: 0.15, + lineWidth: 3, + rope: false, + renderType: "line", + }, }, createBodies: (w, h) => { const bodies = [ @@ -368,8 +396,15 @@ render: { strokeStyle: chain.color, lineWidth: linkCfg.lineWidth ?? 3, + type: linkCfg.renderType || "line", }, }); + constraint.plugin = { + restLength: dist * (linkCfg.lengthScale ?? 1), + rope: linkCfg.rope ?? false, + baseStiffness: linkCfg.stiffness ?? 0.9, + maxLength: dist * (linkCfg.lengthScale ?? 1), + }; chain.constraints.push(constraint); chain.bodies.push(body); setHighlight(body, true); @@ -565,6 +600,24 @@ }); }); + Events.on(engine, "beforeUpdate", () => { + // Rope-like constraint handling: allow shortening without push-back, tension when stretched. + chain.constraints.forEach((c) => { + if (!c.plugin || !c.plugin.rope) return; + const current = Vector.magnitude( + Vector.sub(c.bodyA.position, c.bodyB.position), + ); + const maxLen = c.plugin.maxLength ?? c.length; + if (current <= maxLen) { + c.length = current; + c.stiffness = 0; + } else { + c.length = maxLen; + c.stiffness = c.plugin.baseStiffness ?? c.stiffness; + } + }); + }); + Events.on(render, "afterRender", () => { if (!chain.active || !chain.pointer || chain.bodies.length === 0) return; const last = chain.bodies[chain.bodies.length - 1];