Fix color matching and blob types

This commit is contained in:
Daddy32
2025-12-13 21:18:33 +01:00
parent 8dfb370d10
commit ed7e12b9c1
3 changed files with 82 additions and 8 deletions

82
main.js
View File

@@ -108,6 +108,7 @@
let levelWon = false;
let timerEndMs = null;
let lastTimerDisplay = null;
let dragConstraint = null;
const makeStorageKey = (sceneId) => `physilinks-highscore-${sceneId}`;
@@ -345,6 +346,7 @@
score = 0;
clearedCount = 0;
clearedByColor = {};
endDrag();
const winCond = currentScene?.config?.winCondition;
if (winCond?.type === "timer") {
const duration = winCond.durationSec ?? 120;
@@ -564,6 +566,39 @@
return hits[0];
};
const getDraggableBody = (point) => {
const draggables = [
...boundaries.filter((b) => b.plugin?.draggable),
...balls.filter((b) => b.plugin?.draggable),
];
const hits = Query.point(draggables, point);
return hits[0];
};
const startDrag = (body, point) => {
endDrag();
dragConstraint = Constraint.create({
pointA: point,
bodyB: body,
stiffness: 0.2,
damping: 0.3,
render: { visible: false },
});
World.add(world, dragConstraint);
};
const updateDrag = (point) => {
if (!dragConstraint) return;
dragConstraint.pointA = point;
};
const endDrag = () => {
if (dragConstraint) {
World.remove(world, dragConstraint);
dragConstraint = null;
}
};
const getPointerPosition = (evt) => {
const rect = render.canvas.getBoundingClientRect();
const clientX = evt.touches ? evt.touches[0].clientX : evt.clientX;
@@ -577,10 +612,20 @@
const handlePointerDown = (evt) => {
if (gameOver || isPaused || levelWon) return;
const point = getPointerPosition(evt);
const dragTarget = getDraggableBody(point);
if (dragTarget) {
startDrag(dragTarget, point);
return;
}
const body = pickBody(point);
if (!body) return;
if (!currentScene?.config?.relaxMode) {
// Only allow linking same colors unless relax mode explicitly opts out.
chain.color = body.plugin.color;
} else {
chain.color = body.plugin.color;
}
chain.active = true;
chain.color = body.plugin.color;
chain.bodies = [body];
chain.constraints = [];
chain.pointer = point;
@@ -589,6 +634,10 @@
};
const handlePointerMove = (evt) => {
if (dragConstraint) {
updateDrag(getPointerPosition(evt));
return;
}
if (!chain.active) return;
if (gameOver || isPaused || levelWon) return;
const point = getPointerPosition(evt);
@@ -603,7 +652,8 @@
}
return;
}
if (body.plugin.color !== chain.color) return;
if (!currentScene?.config?.relaxMode && body.plugin.color !== chain.color)
return;
const maxLinkDist = getMaxLinkDistance();
const dist = Vector.magnitude(
Vector.sub(chain.bodies[chain.bodies.length - 1].position, body.position),
@@ -612,7 +662,13 @@
addToChain(body);
};
const handlePointerUp = () => finishChain(chain.pointer);
const handlePointerUp = () => {
if (dragConstraint) {
endDrag();
return;
}
finishChain(chain.pointer);
};
render.canvas.addEventListener("mousedown", handlePointerDown);
render.canvas.addEventListener("mousemove", handlePointerMove);
@@ -706,7 +762,7 @@
lineWidth: 2,
},
};
if (currentScene?.config?.blobBalls) {
if (currentScene?.config?.blobBalls === "soft") {
const cols = 3;
const rows = 2;
const radius = Math.max(10, config.ballRadius * 0.55);
@@ -737,7 +793,24 @@
});
return { bodies: soft.bodies, constraints: soft.constraints, blobId };
}
if (currentScene?.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 };
return { bodies: [body], constraints: [], blobId: null };
}
const body = Bodies.circle(x, y, config.ballRadius, commonOpts);
body.plugin = { color, hasEntered: false, entryCheckId: null };
return { bodies: [body], constraints: [], blobId: null };
};
@@ -823,6 +896,7 @@
Body.setVelocity(ball, { x: 0, y: 0 });
});
resetChainVisuals();
endDrag();
};
const handleResize = () => {