Stagger floating goal reminders

This commit is contained in:
Daddy32
2025-12-14 13:28:04 +01:00
parent 17d11d062c
commit d7f9fe9af3

View File

@@ -139,6 +139,8 @@
let score = 0;
let highScore = 0;
let longestChainRecord = 0;
const goalMilestoneThresholds = [0.5, 0.75, 0.9];
let announcedGoalMilestones = new Set();
let clearedCount = 0;
let clearedByColor = {};
let gameOver = false;
@@ -483,6 +485,7 @@
score = 0;
clearedCount = 0;
clearedByColor = {};
announcedGoalMilestones.clear();
endDrag();
const winCond = currentScene?.config?.winCondition;
if (winCond?.type === "timer") {
@@ -517,7 +520,6 @@
spawnInitialBurst();
startSpawner();
}
announceGoalMessage();
};
const setHighlight = (body, on) => {
@@ -896,6 +898,7 @@
});
const goal = getGoalState();
ui.setGoal(goal || { label: "—", progress: 0 });
maybeAnnounceGoalProgress(goal);
};
const buildLegend = () => {
@@ -1017,6 +1020,7 @@
label: `${String(Math.floor(remainingSec / 60)).padStart(2, "0")}:${String(remainingSec % 60).padStart(2, "0")}`,
progress: duration > 0 ? (100 * elapsed) / duration : 0,
met: remainingMs <= 0,
hint: "Survive until the timer ends",
};
}
if (winCond.type === "clearCount") {
@@ -1026,6 +1030,7 @@
label: `Clear ${target} balls (${remaining} left)`,
progress: target > 0 ? (100 * clearedCount) / target : 0,
met: clearedCount >= target,
hint: "Clear the required balls",
};
}
if (winCond.type === "score") {
@@ -1035,6 +1040,7 @@
label: `Score ${target} (${remaining} left)`,
progress: target > 0 ? (100 * score) / target : 0,
met: score >= target,
hint: "Reach the score target",
};
}
if (winCond.type === "colorClear" && Array.isArray(winCond.targets)) {
@@ -1062,14 +1068,16 @@
(clearedByColor[normalizeColor(t.color)] || 0) >= (t.count || 0),
),
colors: targets.map((t) => t.color),
hint: "Clear the target colors",
};
}
return null;
};
const formatGoalMessage = (goal) => {
if (!goal || !goal.label || goal.label === "—") return null;
const pieces = [`Goal: ${goal.label}`];
if (!goal) return null;
const title = goal.hint || goal.label || "Goal";
const pieces = [`Goal: ${title}`];
if (Number.isFinite(goal.progress)) {
const pct = Math.max(0, Math.min(100, Math.round(goal.progress)));
pieces.push(`${pct}% complete`);
@@ -1077,8 +1085,12 @@
return pieces.join(" • ");
};
const announceGoalMessage = () => {
const goal = getGoalState();
const maybeAnnounceGoalProgress = (goal) => {
if (!goal || !Number.isFinite(goal.progress)) return;
const fraction = Math.max(0, Math.min(1, goal.progress / 100));
for (const threshold of goalMilestoneThresholds) {
if (fraction >= threshold && !announcedGoalMilestones.has(threshold)) {
announcedGoalMilestones.add(threshold);
const text = config.messages?.text || formatGoalMessage(goal);
if (!text) return;
const colors =
@@ -1092,6 +1104,9 @@
position: config.messages.position,
},
);
break;
}
}
};
const clampBodiesIntoView = (prevWidth, prevHeight) => {