129 lines
3.6 KiB
JavaScript
129 lines
3.6 KiB
JavaScript
(() => {
|
|
const { Bodies, Composites } = Matter;
|
|
const scenes = (window.PhysilinksSceneDefs =
|
|
window.PhysilinksSceneDefs || []);
|
|
|
|
scenes.push({
|
|
id: "relax",
|
|
name: "Relax drift",
|
|
config: {
|
|
gravity: 0.08,
|
|
spawnIntervalMs: 850,
|
|
spawnBatchMin: 3,
|
|
spawnBatchMax: 5,
|
|
spawnFrom: "bottom",
|
|
autoSpawn: true,
|
|
minChain: 2,
|
|
palette: ["#38bdf8", "#f472b6", "#fbbf24", "#22c55e", "#a855f7"],
|
|
ballRadius: 20,
|
|
blobBalls: false,
|
|
noGameOver: true,
|
|
relaxMode: true,
|
|
winCondition: {
|
|
type: "timer",
|
|
durationSec: 120,
|
|
onWin: { setGravity: -0.4, swirlBalls: true },
|
|
},
|
|
link: {
|
|
stiffness: 0.6,
|
|
lengthScale: 1.1,
|
|
damping: 0.1,
|
|
lineWidth: 3,
|
|
rope: true,
|
|
renderType: "line",
|
|
maxLengthMultiplier: 3.8,
|
|
},
|
|
},
|
|
createBodies: (w, h) => {
|
|
const wallThickness = Math.max(30, w * 0.04);
|
|
const wallHeight = h + wallThickness * 2;
|
|
const floorHeight = Math.max(40, h * 0.08);
|
|
const bumperRadius = Math.max(30, Math.min(w, h) * 0.04);
|
|
const makeSoft = (cx, cy, cols, rows, radius, color) => {
|
|
const particleOpts = {
|
|
friction: 0.02,
|
|
frictionStatic: 0.04,
|
|
restitution: 0.02,
|
|
render: { fillStyle: color, strokeStyle: color },
|
|
plugin: { draggable: true, nonLinkable: true },
|
|
};
|
|
const constraintOpts = {
|
|
stiffness: 0.08,
|
|
damping: 0.35,
|
|
render: { visible: false, type: "line", anchors: false },
|
|
};
|
|
const comp = Composites.softBody(
|
|
cx - cols * radius * 1.1,
|
|
cy - rows * radius * 1.1,
|
|
cols,
|
|
rows,
|
|
0,
|
|
0,
|
|
true,
|
|
radius,
|
|
particleOpts,
|
|
constraintOpts,
|
|
);
|
|
comp.bodies.forEach((b) => {
|
|
b.plugin = b.plugin || {};
|
|
b.plugin.draggable = true;
|
|
b.plugin.nonLinkable = true;
|
|
});
|
|
comp.constraints.forEach((c) => {
|
|
c.plugin = { soft: true };
|
|
});
|
|
return comp;
|
|
};
|
|
|
|
const softRadius = Math.max(18, w * 0.025);
|
|
const softA = makeSoft(w * 0.32, h * 0.38, 3, 3, softRadius, "#38bdf8");
|
|
const softB = makeSoft(w * 0.65, h * 0.55, 3, 3, softRadius, "#f472b6");
|
|
const softC = makeSoft(w * 0.5, h * 0.32, 3, 3, softRadius, "#fbbf24");
|
|
|
|
return [
|
|
Bodies.rectangle(
|
|
w / 2,
|
|
h + floorHeight / 2,
|
|
w + wallThickness * 2,
|
|
floorHeight,
|
|
{
|
|
isStatic: true,
|
|
restitution: 0.8,
|
|
render: { fillStyle: "#0ea5e9", strokeStyle: "#0ea5e9" },
|
|
},
|
|
),
|
|
Bodies.rectangle(
|
|
w / 2,
|
|
-wallThickness / 2,
|
|
w + wallThickness * 2,
|
|
wallThickness,
|
|
{
|
|
isStatic: true,
|
|
render: { fillStyle: "#0ea5e9", strokeStyle: "#0ea5e9" },
|
|
},
|
|
),
|
|
Bodies.rectangle(-wallThickness / 2, h / 2, wallThickness, wallHeight, {
|
|
isStatic: true,
|
|
render: { fillStyle: "#7c3aed", strokeStyle: "#7c3aed" },
|
|
}),
|
|
Bodies.rectangle(
|
|
w + wallThickness / 2,
|
|
h / 2,
|
|
wallThickness,
|
|
wallHeight,
|
|
{
|
|
isStatic: true,
|
|
render: { fillStyle: "#7c3aed", strokeStyle: "#7c3aed" },
|
|
},
|
|
),
|
|
...softA.bodies,
|
|
...softA.constraints,
|
|
...softB.bodies,
|
|
...softB.constraints,
|
|
...softC.bodies,
|
|
...softC.constraints,
|
|
];
|
|
},
|
|
});
|
|
})();
|