From a489cd839c4b12d8d704bb8daded2e886f201796 Mon Sep 17 00:00:00 2001 From: Daddy32 Date: Fri, 12 Dec 2025 21:19:03 +0100 Subject: [PATCH] Switch to globals: load scenes and main via script order --- index.html | 4 +- main.js | 150 ++++------------------------------------------------- scenes.js | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 142 deletions(-) create mode 100644 scenes.js diff --git a/index.html b/index.html index 3becc5b..21902be 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,6 @@ rel="stylesheet" /> -
@@ -76,6 +75,7 @@
- + + diff --git a/main.js b/main.js index 59c6bfc..f1dde75 100644 --- a/main.js +++ b/main.js @@ -12,6 +12,8 @@ Vector, } = Matter; + const { scenes = [], defaultSceneId } = window.PhysilinksScenes || {}; + const config = { gravity: 1, spawnIntervalMs: 520, @@ -29,144 +31,6 @@ }, }; - const scenes = [ - { - id: "scene1", - name: "Balanced (default)", - config: { - gravity: 0.88, - spawnIntervalMs: 520, - minChain: 3, - palette: ["#ff595e", "#ffca3a", "#8ac926", "#1982c4", "#6a4c93"], - ballRadius: 38, - link: { - stiffness: 0.85, - lengthScale: 1.05, - damping: 0.08, - lineWidth: 3, - rope: true, - renderType: "line", - maxLengthMultiplier: 3.2, - }, - }, - createBodies: (w, h) => [ - Bodies.rectangle(w / 2, h + 40, w, 80, { - isStatic: true, - restitution: 0.8, - render: { fillStyle: "#0ea5e9", strokeStyle: "#0ea5e9" }, - }), - Bodies.rectangle(-40, h / 2, 80, h * 2, { - isStatic: true, - render: { fillStyle: "#f97316", strokeStyle: "#f97316" }, - }), - Bodies.rectangle(w + 40, h / 2, 80, h * 2, { - isStatic: true, - render: { fillStyle: "#f97316", strokeStyle: "#f97316" }, - }), - Bodies.rectangle(w * 0.25, h * 0.55, 160, 20, { - isStatic: true, - angle: -0.3, - render: { fillStyle: "#22c55e", strokeStyle: "#22c55e" }, - plugin: { rotSpeed: 0.1 }, - }), - Bodies.rectangle(w * 0.7, h * 0.4, 220, 24, { - isStatic: true, - angle: 0.26, - render: { fillStyle: "#a855f7", strokeStyle: "#a855f7" }, - plugin: { rotSpeed: -0.08 }, - }), - ], - }, - { - id: "scene2", - name: "Low-G terraces", - config: { - gravity: 0.65, - spawnIntervalMs: 600, - minChain: 3, - palette: ["#fb7185", "#fbbf24", "#34d399", "#38bdf8"], - ballRadius: 22, - link: { - stiffness: 0.6, - lengthScale: 1, - damping: 0.01, - lineWidth: 4, - rope: false, - renderType: "spring", - maxLengthMultiplier: 6.7, - }, - }, - createBodies: (w, h) => [ - Bodies.rectangle(w / 2, h + 50, w, 100, { - isStatic: true, - restitution: 0.9, - }), - Bodies.rectangle(-50, h / 2, 100, h * 2, { isStatic: true }), - Bodies.rectangle(w + 50, h / 2, 100, h * 2, { isStatic: true }), - Bodies.rectangle(w * 0.2, h * 0.45, 200, 18, { - isStatic: true, - angle: 0.08, - }), - Bodies.rectangle(w * 0.5, h * 0.6, 260, 18, { - isStatic: true, - angle: -0.04, - }), - Bodies.rectangle(w * 0.8, h * 0.42, 180, 18, { - isStatic: true, - angle: 0.14, - }), - ], - }, - { - id: "scene3", - name: "Fast drop maze", - config: { - gravity: 1.25, - spawnIntervalMs: 420, - minChain: 3, - palette: ["#e879f9", "#38bdf8", "#f97316", "#22c55e"], - ballRadius: 16, - link: { - stiffness: 1, - lengthScale: 0.85, - damping: 0.15, - lineWidth: 3, - rope: false, - renderType: "line", - maxLengthMultiplier: 16.8, - }, - }, - createBodies: (w, h) => { - const bodies = [ - Bodies.rectangle(w / 2, h + 40, w, 80, { - isStatic: true, - restitution: 0.75, - }), - Bodies.rectangle(-40, h / 2, 80, h * 2, { isStatic: true }), - Bodies.rectangle(w + 40, h / 2, 80, h * 2, { isStatic: true }), - ]; - for (let i = 0; i < 5; i += 1) { - const x = (w * (i + 1)) / 6; - const y = h * 0.35 + (i % 2 === 0 ? 40 : -30); - bodies.push( - Bodies.circle(x, y, 18, { isStatic: true, restitution: 0.9 }), - ); - } - bodies.push( - Bodies.rectangle(w * 0.3, h * 0.55, 140, 16, { - isStatic: true, - angle: -0.3, - }), - Bodies.rectangle(w * 0.7, h * 0.58, 160, 16, { - isStatic: true, - angle: 0.28, - }), - ); - return bodies; - }, - }, - ]; - const sceneEl = document.getElementById("scene-wrapper"); const activeColorEl = document.getElementById("active-color"); const chainLenEl = document.getElementById("chain-length"); @@ -209,7 +73,13 @@ // Static boundaries and scene-specific obstacles. let boundaries = []; let rotators = []; - let currentScene = scenes[0]; + let currentScene = + scenes.find((s) => s.id === defaultSceneId) || scenes[0] || null; + + if (currentScene && currentScene.config) { + Object.assign(config, currentScene.config); + config.link = { ...currentScene.config.link }; + } const rebuildSceneBodies = () => { boundaries.forEach((b) => World.remove(world, b)); @@ -701,5 +571,5 @@ sceneSelectEl.addEventListener("change", (e) => applyScene(e.target.value)); } populateSceneSelect(); - applyScene(currentScene.id); + applyScene((currentScene && currentScene.id) || defaultSceneId); })(); diff --git a/scenes.js b/scenes.js new file mode 100644 index 0000000..68efa14 --- /dev/null +++ b/scenes.js @@ -0,0 +1,146 @@ +(() => { + const { Bodies } = Matter; + + const scenes = [ + { + id: "scene1", + name: "Balanced (default)", + config: { + gravity: 0.88, + spawnIntervalMs: 520, + minChain: 3, + palette: ["#ff595e", "#ffca3a", "#8ac926", "#1982c4", "#6a4c93"], + ballRadius: 38, + link: { + stiffness: 0.85, + lengthScale: 1.05, + damping: 0.08, + lineWidth: 3, + rope: true, + renderType: "line", + maxLengthMultiplier: 3.2, + }, + }, + createBodies: (w, h) => [ + Bodies.rectangle(w / 2, h + 40, w, 80, { + isStatic: true, + restitution: 0.8, + render: { fillStyle: "#0ea5e9", strokeStyle: "#0ea5e9" }, + }), + Bodies.rectangle(-40, h / 2, 80, h * 2, { + isStatic: true, + render: { fillStyle: "#f97316", strokeStyle: "#f97316" }, + }), + Bodies.rectangle(w + 40, h / 2, 80, h * 2, { + isStatic: true, + render: { fillStyle: "#f97316", strokeStyle: "#f97316" }, + }), + Bodies.rectangle(w * 0.25, h * 0.55, 160, 20, { + isStatic: true, + angle: -0.3, + render: { fillStyle: "#22c55e", strokeStyle: "#22c55e" }, + plugin: { rotSpeed: 0.1 }, + }), + Bodies.rectangle(w * 0.7, h * 0.4, 220, 24, { + isStatic: true, + angle: 0.26, + render: { fillStyle: "#a855f7", strokeStyle: "#a855f7" }, + plugin: { rotSpeed: -0.08 }, + }), + ], + }, + { + id: "scene2", + name: "Low-G terraces", + config: { + gravity: 0.65, + spawnIntervalMs: 600, + minChain: 3, + palette: ["#fb7185", "#fbbf24", "#34d399", "#38bdf8"], + ballRadius: 22, + link: { + stiffness: 0.6, + lengthScale: 1, + damping: 0.01, + lineWidth: 4, + rope: false, + renderType: "spring", + maxLengthMultiplier: 2.7, + }, + }, + createBodies: (w, h) => [ + Bodies.rectangle(w / 2, h + 50, w, 100, { + isStatic: true, + restitution: 0.9, + }), + Bodies.rectangle(-50, h / 2, 100, h * 2, { isStatic: true }), + Bodies.rectangle(w + 50, h / 2, 100, h * 2, { isStatic: true }), + Bodies.rectangle(w * 0.2, h * 0.45, 200, 18, { + isStatic: true, + angle: 0.08, + }), + Bodies.rectangle(w * 0.5, h * 0.6, 260, 18, { + isStatic: true, + angle: -0.04, + }), + Bodies.rectangle(w * 0.8, h * 0.42, 180, 18, { + isStatic: true, + angle: 0.14, + }), + ], + }, + { + id: "scene3", + name: "Fast drop maze", + config: { + gravity: 1.25, + spawnIntervalMs: 420, + minChain: 3, + palette: ["#e879f9", "#38bdf8", "#f97316", "#22c55e"], + ballRadius: 16, + link: { + stiffness: 1, + lengthScale: 0.85, + damping: 0.15, + lineWidth: 3, + rope: false, + renderType: "line", + maxLengthMultiplier: 3.8, + }, + }, + createBodies: (w, h) => { + const bodies = [ + Bodies.rectangle(w / 2, h + 40, w, 80, { + isStatic: true, + restitution: 0.75, + }), + Bodies.rectangle(-40, h / 2, 80, h * 2, { isStatic: true }), + Bodies.rectangle(w + 40, h / 2, 80, h * 2, { isStatic: true }), + ]; + for (let i = 0; i < 5; i += 1) { + const x = (w * (i + 1)) / 6; + const y = h * 0.35 + (i % 2 === 0 ? 40 : -30); + bodies.push( + Bodies.circle(x, y, 18, { isStatic: true, restitution: 0.9 }), + ); + } + bodies.push( + Bodies.rectangle(w * 0.3, h * 0.55, 140, 16, { + isStatic: true, + angle: -0.3, + }), + Bodies.rectangle(w * 0.7, h * 0.58, 160, 16, { + isStatic: true, + angle: 0.28, + }), + ); + return bodies; + }, + }, + ]; + + window.PhysilinksScenes = { + scenes, + defaultSceneId: scenes[0]?.id || "scene1", + }; +})();