From 653710c8a873a0242d8665157ff261f63896af1a Mon Sep 17 00:00:00 2001 From: Daddy32 Date: Mon, 29 Dec 2025 21:11:26 +0100 Subject: [PATCH] Refactor ball body creation --- src/spawn.js | 286 +++++++++++++++++++++++++++------------------------ 1 file changed, 153 insertions(+), 133 deletions(-) diff --git a/src/spawn.js b/src/spawn.js index 6d823d3..3a2076d 100644 --- a/src/spawn.js +++ b/src/spawn.js @@ -117,6 +117,154 @@ config.ballRadius = nextRadius; }; + const createSoftBlob = (x, y, color, commonOpts) => { + const cols = 3; + const rows = 2; + const radius = Math.max(10, config.ballRadius * 0.55); + const soft = Composites.softBody( + x - cols * radius * 1.2, + y - rows * radius * 1.2, + cols, + rows, + 0, + 0, + true, + radius, + commonOpts, + ); + const blobId = `blob-${Date.now()}-${Math.random() + .toString(16) + .slice(2)}`; + soft.bodies.forEach((b) => { + b.plugin = { + color, + hasEntered: false, + entryCheckId: null, + blobId, + }; + }); + soft.constraints.forEach((c) => { + c.plugin = { blobId, blobConstraint: true }; + c.render = c.render || {}; + c.render.type = "line"; + }); + return { bodies: soft.bodies, constraints: soft.constraints, blobId }; + }; + + const createJaggedBall = (x, y, color, commonOpts) => { + const points = []; + const segments = 6; + for (let i = 0; i < segments; i += 1) { + const angle = Math.min((i / segments) * Math.PI * 2, Math.PI * 2); + const variance = 0.6 + Math.random() * 0.5; + const r = config.ballRadius * variance; + points.push({ + x: x + Math.cos(angle) * r, + y: y + Math.sin(angle) * r, + }); + } + const body = Bodies.fromVertices(x, y, [points], commonOpts, true); + body.plugin = { + color, + hasEntered: false, + entryCheckId: null, + shape: "jagged", + }; + return { bodies: [body], constraints: [], blobId: null }; + }; + + const createGiftBall = (x, y, color, commonOpts, scene, debugSpawn) => { + const size = config.ballRadius * 2; + const ribbonSize = Math.max(4, config.ballRadius * 0.35); + const ribbonColor = scene?.config?.giftRibbonColor || "#f8fafc"; + if (debugSpawn) { + console.log("Spawn gift", { + sceneId: scene?.id, + x, + y, + color, + size, + }); + } + const base = Bodies.rectangle(x, y, size, size, { + ...commonOpts, + chamfer: { radius: Math.max(2, config.ballRadius * 0.18) }, + }); + const ribbonRender = { + fillStyle: ribbonColor, + strokeStyle: "#0b1222", + lineWidth: 2, + }; + const verticalRibbon = Bodies.rectangle(x, y, ribbonSize, size * 1.02, { + render: ribbonRender, + }); + const horizontalRibbon = Bodies.rectangle( + x, + y, + size * 1.02, + ribbonSize, + { + render: ribbonRender, + }, + ); + const bow = Bodies.rectangle( + x, + y - size * 0.34, + ribbonSize * 1.4, + ribbonSize * 0.8, + { + render: ribbonRender, + }, + ); + const body = Body.create({ + parts: [base, verticalRibbon, horizontalRibbon, bow], + }); + Body.setPosition(body, { x, y }); + body.restitution = commonOpts.restitution; + body.friction = commonOpts.friction; + body.frictionAir = commonOpts.frictionAir; + body.frictionStatic = commonOpts.frictionStatic; + body.density = commonOpts.density; + body.render = { + ...body.render, + ...commonOpts.render, + visible: true, + }; + body.plugin = { + color, + hasEntered: false, + entryCheckId: null, + shape: "gift", + }; + return { bodies: [body], constraints: [], blobId: null }; + }; + + const createRectBall = (x, y, color, commonOpts) => { + const side = config.ballRadius * 2; + const body = Bodies.rectangle(x, y, side, side, { + ...commonOpts, + chamfer: 0, + }); + body.plugin = { + color, + hasEntered: false, + entryCheckId: null, + shape: "rect", + }; + return { bodies: [body], constraints: [], blobId: null }; + }; + + const createCircleBall = (x, y, color, commonOpts) => { + const body = Bodies.circle(x, y, config.ballRadius, commonOpts); + body.plugin = { + color, + hasEntered: false, + entryCheckId: null, + shape: "circle", + }; + return { bodies: [body], constraints: [], blobId: null }; + }; + const createBallBodies = (x, y, color) => { const scene = getCurrentScene(); const ballPhysics = scene?.config?.ballPhysics || {}; @@ -134,146 +282,18 @@ }, }; if (scene?.config?.blobBalls === "soft") { - const cols = 3; - const rows = 2; - const radius = Math.max(10, config.ballRadius * 0.55); - const soft = Composites.softBody( - x - cols * radius * 1.2, - y - rows * radius * 1.2, - cols, - rows, - 0, - 0, - true, - radius, - commonOpts, - ); - const blobId = `blob-${Date.now()}-${Math.random() - .toString(16) - .slice(2)}`; - soft.bodies.forEach((b) => { - b.plugin = { - color, - hasEntered: false, - entryCheckId: null, - blobId, - }; - }); - soft.constraints.forEach((c) => { - c.plugin = { blobId, blobConstraint: true }; - c.render = c.render || {}; - c.render.type = "line"; - }); - return { bodies: soft.bodies, constraints: soft.constraints, blobId }; + return createSoftBlob(x, y, color, commonOpts); } if (scene?.config?.blobBalls === "jagged") { - const points = []; - const segments = 6; - for (let i = 0; i < segments; i += 1) { - const angle = Math.min((i / segments) * Math.PI * 2, Math.PI * 2); - const variance = 0.6 + Math.random() * 0.5; - const r = config.ballRadius * variance; - points.push({ - x: x + Math.cos(angle) * r, - y: y + Math.sin(angle) * r, - }); - } - const body = Bodies.fromVertices(x, y, [points], commonOpts, true); - body.plugin = { - color, - hasEntered: false, - entryCheckId: null, - shape: "jagged", - }; - return { bodies: [body], constraints: [], blobId: null }; + return createJaggedBall(x, y, color, commonOpts); } if (scene?.config?.ballShape === "gift") { - const size = config.ballRadius * 2; - const ribbonSize = Math.max(4, config.ballRadius * 0.35); - const ribbonColor = scene?.config?.giftRibbonColor || "#f8fafc"; - if (debugSpawn) { - console.log("Spawn gift", { - sceneId: scene?.id, - x, - y, - color, - size, - }); - } - const base = Bodies.rectangle(x, y, size, size, { - ...commonOpts, - chamfer: { radius: Math.max(2, config.ballRadius * 0.18) }, - }); - const ribbonRender = { - fillStyle: ribbonColor, - strokeStyle: "#0b1222", - lineWidth: 2, - }; - const verticalRibbon = Bodies.rectangle(x, y, ribbonSize, size * 1.02, { - render: ribbonRender, - }); - const horizontalRibbon = Bodies.rectangle( - x, - y, - size * 1.02, - ribbonSize, - { - render: ribbonRender, - }, - ); - const bow = Bodies.rectangle( - x, - y - size * 0.34, - ribbonSize * 1.4, - ribbonSize * 0.8, - { - render: ribbonRender, - }, - ); - const body = Body.create({ - parts: [base, verticalRibbon, horizontalRibbon, bow], - }); - Body.setPosition(body, { x, y }); - body.restitution = commonOpts.restitution; - body.friction = commonOpts.friction; - body.frictionAir = commonOpts.frictionAir; - body.frictionStatic = commonOpts.frictionStatic; - body.density = commonOpts.density; - body.render = { - ...body.render, - ...commonOpts.render, - visible: true, - }; - body.plugin = { - color, - hasEntered: false, - entryCheckId: null, - shape: "gift", - }; - return { bodies: [body], constraints: [], blobId: null }; + return createGiftBall(x, y, color, commonOpts, scene, debugSpawn); } if (scene?.config?.ballShape === "rect") { - const side = config.ballRadius * 2; - const body = Bodies.rectangle(x, y, side, side, { - ...commonOpts, - chamfer: 0, - }); - body.plugin = { - color, - hasEntered: false, - entryCheckId: null, - shape: "rect", - }; - return { bodies: [body], constraints: [], blobId: null }; + return createRectBall(x, y, color, commonOpts); } - const body = Bodies.circle(x, y, config.ballRadius, commonOpts); - body.plugin = { - color, - hasEntered: false, - entryCheckId: null, - shape: "circle", - }; - return { bodies: [body], constraints: [], blobId: null }; + return createCircleBall(x, y, color, commonOpts); }; const spawnBall = () => {