Tweak relax scene soft blobs and spawn batches

This commit is contained in:
Daddy32
2025-12-13 20:46:50 +01:00
parent dfb358fce2
commit 45a7a6cef4
2 changed files with 90 additions and 18 deletions

60
main.js
View File

@@ -202,23 +202,51 @@
const y = spawnFromBottom const y = spawnFromBottom
? height + config.ballRadius * 2 ? height + config.ballRadius * 2
: -config.ballRadius * 2; : -config.ballRadius * 2;
const ball = createBallBody(x, y, color); const batchMin = currentScene?.config?.spawnBatchMin ?? 1;
ball.plugin = { const batchMax = currentScene?.config?.spawnBatchMax ?? 1;
color, const batchCount =
hasEntered: false, batchMin === batchMax
entryCheckId: null, ? batchMin
squishX: 1, : Math.max(
squishY: 1, batchMin,
}; Math.floor(Math.random() * (batchMax - batchMin + 1)) + batchMin,
balls.push(ball); );
World.add(world, ball); for (let i = 0; i < batchCount; i += 1) {
ball.plugin.entryCheckId = setTimeout(() => { const blob = createBallBodies(
ball.plugin.entryCheckId = null; Math.min(
if (gameOver) return; Math.max(
if (!ball.plugin.hasEntered && Math.abs(ball.velocity.y) < 0.2) { config.ballRadius + 10,
triggerGameOver(); x + (i - batchCount / 2) * config.ballRadius * 1.5,
),
width - config.ballRadius - 10,
),
y +
i *
(spawnFromBottom
? -config.ballRadius * 0.5
: config.ballRadius * 0.5),
color,
);
if (blob.constraints.length > 0 && blob.blobId) {
blobConstraints.set(blob.blobId, blob.constraints);
} }
}, 1500); blob.bodies.forEach((body) => {
balls.push(body);
World.add(world, body);
if (!currentScene?.config?.noGameOver) {
body.plugin.entryCheckId = setTimeout(() => {
body.plugin.entryCheckId = null;
if (gameOver) return;
if (!body.plugin.hasEntered && Math.abs(body.velocity.y) < 0.2) {
triggerGameOver();
}
}, 1500);
}
});
if (blob.constraints.length > 0) {
World.add(world, blob.constraints);
}
}
}; };
const startSpawner = () => { const startSpawner = () => {

View File

@@ -1,5 +1,5 @@
(() => { (() => {
const { Bodies } = Matter; const { Bodies, Composites } = Matter;
const scenes = (window.PhysilinksSceneDefs = const scenes = (window.PhysilinksSceneDefs =
window.PhysilinksSceneDefs || []); window.PhysilinksSceneDefs || []);
@@ -16,7 +16,7 @@
minChain: 2, minChain: 2,
palette: ["#38bdf8", "#f472b6", "#fbbf24", "#22c55e", "#a855f7"], palette: ["#38bdf8", "#f472b6", "#fbbf24", "#22c55e", "#a855f7"],
ballRadius: 20, ballRadius: 20,
blobBalls: true, blobBalls: false,
noGameOver: true, noGameOver: true,
winCondition: { winCondition: {
type: "timer", type: "timer",
@@ -38,6 +38,46 @@
const wallHeight = h + wallThickness * 2; const wallHeight = h + wallThickness * 2;
const floorHeight = Math.max(40, h * 0.08); const floorHeight = Math.max(40, h * 0.08);
const bumperRadius = Math.max(30, Math.min(w, h) * 0.04); 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.35, h * 0.4, 3, 3, softRadius, "#38bdf8");
const softB = makeSoft(w * 0.65, h * 0.55, 3, 3, softRadius, "#f472b6");
return [ return [
Bodies.rectangle( Bodies.rectangle(
w / 2, w / 2,
@@ -84,6 +124,10 @@
restitution: 1.05, restitution: 1.05,
render: { fillStyle: "#22c55e", strokeStyle: "#22c55e" }, render: { fillStyle: "#22c55e", strokeStyle: "#22c55e" },
}), }),
...softA.bodies,
...softA.constraints,
...softB.bodies,
...softB.constraints,
]; ];
}, },
}); });