99 lines
4.5 KiB
JavaScript
99 lines
4.5 KiB
JavaScript
// timer.js
|
|
import * as state from './state.js';
|
|
import { GAME_STATES } from './config.js';
|
|
import audioManager from './audio.js';
|
|
|
|
let timerInterval = null;
|
|
let onTimerTickCallback = null; // Callback for UI updates
|
|
let onPlayerSwitchCallback = null; // Callback for when player switches due to time running out
|
|
let onGameOverCallback = null; // Callback for when all players run out of time
|
|
|
|
export function initTimer(options) {
|
|
onTimerTickCallback = options.onTimerTick;
|
|
onPlayerSwitchCallback = options.onPlayerSwitch;
|
|
onGameOverCallback = options.onGameOver;
|
|
}
|
|
|
|
export function startTimer() {
|
|
if (timerInterval) clearInterval(timerInterval); // Clear existing interval if any
|
|
|
|
// Stop any previous sounds (like low time warning) before starting fresh
|
|
audioManager.stopAllSounds(); // Consider if this is too aggressive
|
|
|
|
timerInterval = setInterval(() => {
|
|
const currentPlayerIndex = state.getCurrentPlayerIndex();
|
|
const currentPlayer = state.getCurrentPlayer(); // Get player data after index
|
|
|
|
if (!currentPlayer) {
|
|
console.warn("Timer running but no current player found.");
|
|
stopTimer();
|
|
return;
|
|
}
|
|
|
|
// Only decrease time if the current player has time left
|
|
if (currentPlayer.remainingTime > 0) {
|
|
const newTime = currentPlayer.remainingTime - 1;
|
|
state.updatePlayerTime(currentPlayerIndex, newTime); // Update state
|
|
|
|
// Play timer sounds
|
|
audioManager.playTimerSound(newTime);
|
|
|
|
// Notify UI to update
|
|
if (onTimerTickCallback) onTimerTickCallback();
|
|
|
|
} else { // Current player's time just hit 0 or was already 0
|
|
// Ensure time is exactly 0 if it somehow went negative (unlikely with check above)
|
|
if(currentPlayer.remainingTime < 0) {
|
|
state.updatePlayerTime(currentPlayerIndex, 0);
|
|
}
|
|
|
|
// Stop this player's timer tick sound if it was playing
|
|
// audioManager.stop('timerTick'); // Or specific low time sound
|
|
|
|
// Play time expired sound (only once)
|
|
// Check if we just hit zero to avoid playing repeatedly
|
|
// This logic might be complex, audioManager could handle idempotency
|
|
if (currentPlayer.remainingTime === 0 && !currentPlayer.timeExpiredSoundPlayed) {
|
|
audioManager.playTimerExpired();
|
|
// We need a way to mark that the sound played for this player this turn.
|
|
// This might require adding a temporary flag to the player state,
|
|
// or handling it within the audioManager. Let's assume audioManager handles it for now.
|
|
}
|
|
|
|
|
|
// Check if the game should end or switch player
|
|
if (state.areAllTimersFinished()) {
|
|
stopTimer();
|
|
if (onGameOverCallback) onGameOverCallback();
|
|
} else {
|
|
// Find the *next* player who still has time
|
|
const nextPlayerIndex = state.findNextPlayerWithTime(); // This finds ANY player with time
|
|
if (nextPlayerIndex !== -1 && nextPlayerIndex !== currentPlayerIndex) {
|
|
// Switch player
|
|
if (onPlayerSwitchCallback) onPlayerSwitchCallback(nextPlayerIndex);
|
|
// Play switch sound (might be handled in app.js based on state change)
|
|
// audioManager.play('playerSwitch'); // Or let app.js handle sounds based on actions
|
|
// Immediately update UI after switch
|
|
if (onTimerTickCallback) onTimerTickCallback();
|
|
} else if (nextPlayerIndex === -1) {
|
|
// This case shouldn't be reached if areAllTimersFinished is checked first, but as a safeguard:
|
|
console.warn("Timer tick: Current player out of time, but no next player found, yet not all timers finished?");
|
|
stopTimer(); // Stop timer if state is inconsistent
|
|
if (onGameOverCallback) onGameOverCallback(); // Treat as game over
|
|
}
|
|
// If nextPlayerIndex is the same as currentPlayerIndex, means others are out of time, let this timer continue (or rather, stop ticking down as remainingTime is 0)
|
|
}
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
export function stopTimer() {
|
|
clearInterval(timerInterval);
|
|
timerInterval = null;
|
|
// Optionally stop timer sounds here if needed
|
|
// audioManager.stop('timerTick');
|
|
}
|
|
|
|
export function isTimerRunning() {
|
|
return timerInterval !== null;
|
|
} |