Feat: Add 5-second delay and winning move highlight for game over

This commit is contained in:
2025-12-23 20:34:50 +11:00
parent f35b25b903
commit d1bcf36887
2 changed files with 40 additions and 13 deletions

30
game.js
View File

@@ -67,7 +67,7 @@ class Connect5Game {
} }
this.updateStatus(); this.updateStatus();
// Set initial board class // Set initial board class
this.boardElement.classList.add(`turn-${this.currentPlayer.toLowerCase()}`); this.boardElement.classList.add(`turn-${this.currentPlayer.toLowerCase()}`);
} }
@@ -82,7 +82,7 @@ class Connect5Game {
if (!multiplayerClient.myTurn) { if (!multiplayerClient.myTurn) {
return; // Not our turn in multiplayer return; // Not our turn in multiplayer
} }
// Send move to server // Send move to server
const moveSent = multiplayerClient.makeMove(row, col); const moveSent = multiplayerClient.makeMove(row, col);
if (!moveSent) return; if (!moveSent) return;
@@ -103,7 +103,11 @@ class Connect5Game {
this.gameActive = false; this.gameActive = false;
this.scores[this.currentPlayer]++; this.scores[this.currentPlayer]++;
this.updateScores(); this.updateScores();
this.showVictoryOverlay();
// Delay showing visual overlay for 5 seconds to show winning lights
setTimeout(() => {
this.showVictoryOverlay();
}, 5000);
return; return;
} }
@@ -218,8 +222,10 @@ class Connect5Game {
// Update board class for ghost piece // Update board class for ghost piece
if (this.boardElement) { if (this.boardElement) {
this.boardElement.classList.remove('turn-x', 'turn-o'); this.boardElement.classList.remove("turn-x", "turn-o");
this.boardElement.classList.add(`turn-${this.currentPlayer.toLowerCase()}`); this.boardElement.classList.add(
`turn-${this.currentPlayer.toLowerCase()}`
);
} }
// Update the player display style // Update the player display style
@@ -252,13 +258,13 @@ class Connect5Game {
this.currentPlayer = "X"; this.currentPlayer = "X";
this.gameActive = true; this.gameActive = true;
this.hideVictoryOverlay(); this.hideVictoryOverlay();
// Reset turn label to default // Reset turn label to default
const turnLabel = document.getElementById('turnLabel'); const turnLabel = document.getElementById("turnLabel");
if (turnLabel) { if (turnLabel) {
turnLabel.textContent = 'Current Turn:'; turnLabel.textContent = "Current Turn:";
} }
this.initializeBoard(); this.initializeBoard();
} }
} }
@@ -267,11 +273,11 @@ class Connect5Game {
window.game = null; window.game = null;
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
window.game = new Connect5Game(); window.game = new Connect5Game();
// Enable multiplayer button now that game is ready // Enable multiplayer button now that game is ready
const multiplayerBtn = document.getElementById('multiplayerModeBtn'); const multiplayerBtn = document.getElementById("multiplayerModeBtn");
if (multiplayerBtn) { if (multiplayerBtn) {
multiplayerBtn.disabled = false; multiplayerBtn.disabled = false;
console.log('✅ Game initialized, multiplayer button enabled'); console.log("✅ Game initialized, multiplayer button enabled");
} }
}); });

View File

@@ -482,6 +482,7 @@ class MultiplayerClient {
col: col col: col
}); });
this.lastMyMove = { row, col };
return true; return true;
} }
@@ -504,6 +505,7 @@ class MultiplayerClient {
// Handle opponent move // Handle opponent move
handleOpponentMove(data) { handleOpponentMove(data) {
this.lastOpponentMove = { row: data.row, col: data.col };
// Place opponent's piece on board // Place opponent's piece on board
this.game.currentPlayer = data.symbol; this.game.currentPlayer = data.symbol;
@@ -568,7 +570,25 @@ class MultiplayerClient {
const subtitle = document.getElementById('gameOverMessage'); const subtitle = document.getElementById('gameOverMessage');
if (modal && icon && title && subtitle) { if (modal && icon && title && subtitle) {
// Set icon and title based on result
// Highlight winning move if applicable
if (this.game && (data.reason === 'win' || data.reason === 'loss')) {
try {
const move = data.reason === 'win' ? this.lastMyMove : this.lastOpponentMove;
if (move) {
// We temporarily set gameActive to true to allow checkWin to run purely for highlighting
// (checkWin doesn't check gameActive, but just in case)
// Actually checkWin calculates and calls highlightWinningCells
this.game.checkWin(move.row, move.col);
}
} catch (e) {
console.error("Error highlighting winning move:", e);
}
}
// Delay showing the modal for 5 seconds
setTimeout(() => {
// Set icon and title based on result
if (data.reason === 'win' || data.reason === 'opponent_abandoned') { if (data.reason === 'win' || data.reason === 'opponent_abandoned') {
icon.textContent = '🏆'; icon.textContent = '🏆';
title.textContent = 'Victory!'; title.textContent = 'Victory!';
@@ -592,6 +612,7 @@ class MultiplayerClient {
// Show modal // Show modal
modal.classList.add('active'); modal.classList.add('active');
}, 5000);
} }
} }