Add pop clear animation for cleared chains

This commit is contained in:
Daddy32
2025-12-16 20:21:58 +01:00
parent c4053ad8b7
commit 065023abb4
6 changed files with 169 additions and 14 deletions

View File

@@ -94,6 +94,71 @@
chain.constraints.forEach((c) => World.remove(world, c));
};
const collectClearTargets = () => {
const targets = [];
const seen = new Set();
const blobIds = new Set();
const addBall = (ball) => {
if (!ball || seen.has(ball.id)) return;
seen.add(ball.id);
const radius =
typeof ball.circleRadius === "number"
? ball.circleRadius
: Math.max(
Math.abs(ball.bounds.max.x - ball.bounds.min.x),
Math.abs(ball.bounds.max.y - ball.bounds.min.y),
) / 2 || config.ballRadius;
targets.push({
x: ball.position.x,
y: ball.position.y,
color: ball.plugin?.color || ball.render?.fillStyle,
radius,
shape: ball.plugin?.shape || "circle",
});
};
chain.bodies.forEach((body) => {
if (body.plugin?.blobId) {
blobIds.add(body.plugin.blobId);
}
addBall(body);
});
blobIds.forEach((id) => {
state.balls
.filter((b) => b.plugin?.blobId === id)
.forEach((b) => addBall(b));
});
return targets;
};
const runClearAnimation = (targets) => {
if (!targets.length || !ui?.spawnClearEffects) return;
const linkCfg = config.link || {};
const clearCfg = linkCfg.clearAnimation || {};
const { render: renderOverride, ...animCfg } = clearCfg;
const currentScene = getCurrentScene();
let handled = false;
if (typeof renderOverride === "function") {
try {
const result = renderOverride({
targets,
config: animCfg,
scene: currentScene,
ui,
});
handled = result !== false;
} catch (err) {
console.error("clearAnimation render failed", err);
}
}
if (!handled) {
ui.spawnClearEffects(targets, { type: clearCfg.type, ...animCfg });
}
};
const removeChainBodies = () => {
const blobIds = new Set();
chain.bodies.forEach((body) => {
@@ -178,6 +243,7 @@
updateLongestChain(chainLength);
const { gain, isNegativeProgress } = getChainScoreState();
state.score += gain;
const clearTargets = collectClearTargets();
state.clearedCount += chainLength;
if (state.score > state.highScore) {
state.highScore = state.score;
@@ -185,6 +251,7 @@
}
ui.spawnScorePopup(releasePoint || chain.pointer, gain, chain.color);
removeChainConstraints();
runClearAnimation(clearTargets);
removeChainBodies();
if (isNegativeProgress) {
applyNegativeProgressPenalty(chainLength);