const canvas = document.getElementById('interactiveCanvas'); const ctx = canvas.getContext('2d'); // --- NEW: Get references to overlay elements --- const gameOverOverlay = document.getElementById('gameOverOverlay'); const gameOverTextEl = document.getElementById('gameOverText'); // Though not strictly needed if text doesn't change const gameOverCountdownEl = document.getElementById('gameOverCountdown'); // --- Game State --- let isGameOver = false; let gameOverTime = null; const gameOverCooldownDuration = 5000; let isPlayerControlled = false; let pendingDirection = null; // ... (Keep Grid, Color, Snake, Collectible, Effect settings) ... // ... (Keep Utility Functions, Setup Functions: setCanvasSize, initializeSnake, placeCollectible, initializeCollectibles) ... function init() { // Reset game state fully isGameOver = false; gameOverTime = null; isPlayerControlled = false; pendingDirection = null; // --- HIDE Game Over Overlay --- if (gameOverOverlay) { gameOverOverlay.style.display = 'none'; gameOverOverlay.style.opacity = '0'; } // Reset countdown text if(gameOverCountdownEl) gameOverCountdownEl.textContent = ''; setCanvasSize(); initializeSnake(); initializeCollectibles(); clickEffects = []; eatingEffects = []; frameCount = 0; // document.body.focus(); // Optional focus } // --- Drawing Functions --- // ... (Keep drawGrid, drawSnake, drawCollectibles, drawEffects, drawClickEffect, drawEatingEffect, hexToRgb) ... // --- REMOVED: drawGameOverScreen function --- // --- REMOVED: clamp function (now handled by CSS clamp) --- // --- AI & Update Functions --- // ... (Keep findClosestCollectible, getNextDirection, moveSnake) ... // --- Main Loop --- function animate() { requestAnimationFrame(animate); // --- Game Logic Update --- if (!isGameOver) { frameCount++; if (frameCount % snakeSpeed === 0) { moveSnake(); } } // --- Drawing (Always runs, canvas only) --- ctx.clearRect(0, 0, canvas.width, canvas.height); drawGrid(); drawCollectibles(); drawSnake(); // Draws based on current state drawEffects(clickEffects, drawClickEffect); drawEffects(eatingEffects, drawEatingEffect); // --- Game Over Cooldown & Restart Logic (using HTML Overlay) --- if (isGameOver) { const elapsed = performance.now() - gameOverTime; const remaining = gameOverCooldownDuration - elapsed; // --- SHOW/UPDATE Game Over Overlay --- if (gameOverOverlay.style.display === 'none') { gameOverOverlay.style.display = 'flex'; // Make it visible // Force reflow before changing opacity for transition to work void gameOverOverlay.offsetWidth; gameOverOverlay.style.opacity = '1'; // Fade it in } if (remaining <= 0) { init(); // Restart the game return; // Exit animate immediately after init } else { // Update the countdown text in the HTML overlay const secondsLeft = Math.ceil(remaining / 1000); gameOverCountdownEl.textContent = `Restarting in ${secondsLeft}...`; } } } // --- Event Listeners --- // ... (Keep resize listener) ... // ... (Keep keydown listener) ... // ... (Keep click listener) ... // --- Initialization --- init(); animate();