From 1dc6f3cc9e42379511d93fcd797e3bba22921bcc Mon Sep 17 00:00:00 2001 From: gauvainboiche Date: Tue, 31 Mar 2026 23:35:08 +0200 Subject: [PATCH] fix: Adding color fade-in for tile reveal --- public/src/game.js | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/public/src/game.js b/public/src/game.js index 115c00e..0e2c4fd 100644 --- a/public/src/game.js +++ b/public/src/game.js @@ -50,6 +50,38 @@ export const teamCooldownEndMs = { blue: 0, red: 0 }; let rafId = 0; let lastPointerEvent = null; +// ── Tile fade-in animation ──────────────────────────────────────────────────── + +/** key → timestamp (ms) when the tile was first revealed */ +const tileRevealTime = new Map(); +const TILE_FADE_MS = 500; +let fadeRafId = 0; + +function markTileReveal(key) { + tileRevealTime.set(key, Date.now()); + if (!fadeRafId) scheduleFadeFrame(); +} + +function scheduleFadeFrame() { + fadeRafId = requestAnimationFrame(() => { + fadeRafId = 0; + draw(); + // Keep looping while any tile is still fading + const now = Date.now(); + const stillFading = [...tileRevealTime.values()].some(t => now - t < TILE_FADE_MS); + if (stillFading) scheduleFadeFrame(); + }); +} + +/** Returns the fill opacity multiplier for a tile (0–1). */ +function tileAlpha(key) { + const t = tileRevealTime.get(key); + if (t === undefined) return 1; + const progress = (Date.now() - t) / TILE_FADE_MS; + if (progress >= 1) { tileRevealTime.delete(key); return 1; } + return progress; +} + // ── Zoom / Pan state ────────────────────────────────────────────────────────── const MIN_ZOOM = 1; @@ -594,10 +626,13 @@ export function draw() { if (!isExploitable(x, y)) continue; const k = cellKey(x, y); const meta = cellMeta(k); + const alpha = tileAlpha(k); + ctx.globalAlpha = alpha; if (!meta) ctx.fillStyle = COLOR_RING_IDLE; else if (meta.discoveredBy !== currentTeam) ctx.fillStyle = COLOR_OPPONENT_GREY; else ctx.fillStyle = currentTeam === "blue" ? COLOR_BLUE_DISCOVERED : COLOR_RED_DISCOVERED; ctx.fillRect(x * cw, y * ch, cw, ch); + ctx.globalAlpha = 1; } } @@ -670,7 +705,9 @@ function refreshCursorFromLast() { // ── Selection display ───────────────────────────────────────────────────────── function applyRevealPayload(cell) { - cells.set(cellKey(cell.x, cell.y), { + const _revealKey = cellKey(cell.x, cell.y); + markTileReveal(_revealKey); + cells.set(_revealKey, { discoveredBy: cell.discoveredBy ?? currentTeam, hasPlanet: Boolean(cell.hasPlanet), planet: cell.planet ?? null, @@ -774,6 +811,7 @@ async function onCanvasClick(ev) { else milDeductRed = data.deductions.red ?? milDeductRed; // Transfer tile in local cells Map const existing = cells.get(key); + markTileReveal(key); cells.set(key, { ...existing, discoveredBy: currentTeam }); hint.textContent = `⚔️ Tuile (${cell.x},${cell.y}) conquise !`; updateEconomyDisplay();