feat(confetti): spawn small amount when an achievement is unlocked

This commit is contained in:
2026-01-31 20:49:23 +01:00
parent 41c3238b3b
commit df3a78560b
2 changed files with 11 additions and 6 deletions

View File

@@ -43,6 +43,8 @@ export type ConfettiParticle = {
type Spawner = { type Spawner = {
frame: number; frame: number;
accumulator: number; accumulator: number;
particleCount: number;
duration: number;
}; };
const particles: ConfettiParticle[] = []; const particles: ConfettiParticle[] = [];
@@ -51,7 +53,7 @@ const spawners: Spawner[] = [];
const spawnParticle = () => { const spawnParticle = () => {
particles.push({ particles.push({
x: Math.random() * LOGICAL_WIDTH, x: Math.random() * LOGICAL_WIDTH,
y: -(30 + Math.random() * 20), y: -(Math.random() * 20),
vx: (Math.random() - 0.5) * VX_RANGE, vx: (Math.random() - 0.5) * VX_RANGE,
vy: VY_MIN + Math.random() * VY_RANGE, vy: VY_MIN + Math.random() * VY_RANGE,
width: WIDTH_MIN + Math.random() * WIDTH_RANGE, width: WIDTH_MIN + Math.random() * WIDTH_RANGE,
@@ -64,18 +66,19 @@ const spawnParticle = () => {
}); });
}; };
const spawn = () => { const spawn = (particleCount = PARTICLE_COUNT, duration = SPAWN_DURATION) => {
spawners.push({ frame: 0, accumulator: 0 }); spawners.push({ frame: 0, accumulator: 0, particleCount, duration });
}; };
const update = () => { const update = () => {
for (let s = spawners.length - 1; s >= 0; s -= 1) { for (let s = spawners.length - 1; s >= 0; s -= 1) {
const spawner = spawners[s]!; const spawner = spawners[s]!;
if (spawner.frame < SPAWN_DURATION) { if (spawner.frame < spawner.duration) {
const progress = spawner.frame / SPAWN_DURATION; const progress = spawner.frame / spawner.duration;
const inv = 1 - progress; const inv = 1 - progress;
const rate = inv * inv; const rate = inv * inv;
spawner.accumulator += rate * (PARTICLE_COUNT / SPAWN_DURATION) * 3; spawner.accumulator +=
rate * (spawner.particleCount / spawner.duration) * 3;
const count = Math.floor(spawner.accumulator); const count = Math.floor(spawner.accumulator);
spawner.accumulator -= count; spawner.accumulator -= count;

View File

@@ -62,6 +62,8 @@ export const useAchievementsStore = defineStore("achievements", () => {
if (storage.value.unlocked.length === ACHIEVEMENTS.length) { if (storage.value.unlocked.length === ACHIEVEMENTS.length) {
confetti.spawn(); confetti.spawn();
} else {
confetti.spawn(50, 350);
} }
return true; return true;