Add lava lamp scene with soft-body blobs

This commit is contained in:
Daddy32
2025-12-13 19:54:20 +01:00
parent 357922510a
commit f57e993964
6 changed files with 337 additions and 53 deletions

97
scenes/scene-lavalamp.js Normal file
View File

@@ -0,0 +1,97 @@
(() => {
const { Bodies, Body } = Matter;
const scenes = (window.PhysilinksSceneDefs =
window.PhysilinksSceneDefs || []);
const makeCurveSegments = (cx, h, amp, thickness, segments) => {
const segs = [];
const stepY = h / segments;
let prevX = cx;
let prevY = 0;
for (let i = 0; i < segments; i += 1) {
const y = stepY * (i + 1);
const t = y / h;
const x = cx + Math.sin(t * Math.PI * 1.5) * amp;
const dx = x - prevX;
const dy = y - prevY;
const len = Math.max(1, Math.sqrt(dx * dx + dy * dy));
const angle = Math.atan2(dy, dx);
segs.push(
Bodies.rectangle((prevX + x) / 2, (prevY + y) / 2, thickness, len, {
isStatic: true,
angle,
render: { fillStyle: "#14213a", strokeStyle: "#14213a" },
plugin: { curve: true },
}),
);
prevX = x;
prevY = y;
}
return segs;
};
scenes.push({
id: "scene-lava",
name: "Lava drift",
config: {
gravity: -0.1,
spawnIntervalMs: 180,
spawnFrom: "bottom",
autoSpawn: true,
minChain: 3,
palette: ["#f472b6", "#38bdf8", "#fbbf24", "#a855f7", "#22c55e"],
ballRadius: 26,
blobBalls: true,
winCondition: {
type: "score",
target: 25000,
onWin: { setGravity: -0.55, removeCurves: true },
nextSceneId: "scene-grid",
},
link: {
stiffness: 0.7,
lengthScale: 1.05,
damping: 0.12,
lineWidth: 3,
rope: true,
renderType: "line",
maxLengthMultiplier: 4.8,
},
},
createBodies: (w, h) => {
const wallThickness = Math.max(24, w * 0.05);
const amp = Math.max(40, w * 0.08);
const segments = 12;
const curves = [
...makeCurveSegments(w * 0.33, h, amp, wallThickness, segments),
...makeCurveSegments(w * 0.67, h, amp * 0.95, wallThickness, segments),
];
// Gentle paddles that sway slightly
/*
const paddleWidth = Math.max(120, w * 0.18);
const paddleHeight = Math.max(12, h * 0.018);
const paddles = [
Bodies.rectangle(w * 0.45, h * 0.65, paddleWidth, paddleHeight, {
isStatic: true,
angle: -0.08,
render: { fillStyle: "#0ea5e9", strokeStyle: "#0ea5e9" },
plugin: {
oscillate: { axis: "x", amplitude: w * 0.05, speed: 0.7 },
},
}),
Bodies.rectangle(w * 0.58, h * 0.4, paddleWidth * 0.85, paddleHeight, {
isStatic: true,
angle: 0.12,
render: { fillStyle: "#f59e0b", strokeStyle: "#f59e0b" },
plugin: {
oscillate: { axis: "x", amplitude: w * 0.04, speed: 1.0 },
},
}),
];
*/
return [...curves];
},
});
})();