- add lobby, game, leaderboard, results pages - add scripts: storage, lobby, game, drawing, scoring, countries - add styles: main, lobby, game - unify header/footer across all pages - show lobby name in lobby view - remove clear board from leaderboard
159 lines
4.1 KiB
JavaScript
159 lines
4.1 KiB
JavaScript
// game.js — round management, timer, submit
|
|
|
|
const TOTAL_ROUNDS = 3;
|
|
const ROUND_DURATION = 60; // seconds
|
|
|
|
let roundCountries = [];
|
|
let currentRound = 0;
|
|
let scores = [];
|
|
let timerInterval = null;
|
|
let timeLeft = ROUND_DURATION;
|
|
|
|
// ── DOM refs
|
|
const elCountryName = document.getElementById("country-name");
|
|
const elCountryHint = document.getElementById("country-hint");
|
|
const elRoundNum = document.getElementById("round-num");
|
|
const elTimerNum = document.getElementById("timer-num");
|
|
const elTimerBar = document.getElementById("timer-bar");
|
|
const elBtnClear = document.getElementById("btn-clear");
|
|
const elBtnSubmit = document.getElementById("btn-submit");
|
|
const elCanvas = document.getElementById("draw-canvas");
|
|
|
|
// ── Init
|
|
async function initGame() {
|
|
await Countries.loadCountries();
|
|
roundCountries = Countries.getRandomCountries(TOTAL_ROUNDS);
|
|
currentRound = 0;
|
|
scores = [];
|
|
startRound();
|
|
}
|
|
|
|
// ── Round
|
|
function startRound() {
|
|
const country = roundCountries[currentRound];
|
|
|
|
// Update UI
|
|
elRoundNum.textContent = currentRound + 1;
|
|
elCountryName.textContent = country.name;
|
|
elCountryHint.textContent = country.hint || "";
|
|
|
|
// Round pips
|
|
if (typeof window.updateRoundPips === "function") {
|
|
window.updateRoundPips(currentRound + 1);
|
|
}
|
|
|
|
// Reset canvas placeholder
|
|
document.getElementById("canvas-wrap")?.classList.remove("has-drawing");
|
|
|
|
// Cities on canvas
|
|
Drawing.clear();
|
|
Drawing.setCities(country.cities || []);
|
|
|
|
// Timer
|
|
timeLeft = ROUND_DURATION;
|
|
updateTimerUI();
|
|
clearInterval(timerInterval);
|
|
timerInterval = setInterval(tickTimer, 1000);
|
|
|
|
// Button state
|
|
elBtnSubmit.disabled = false;
|
|
elBtnSubmit.textContent = currentRound < TOTAL_ROUNDS - 1
|
|
? "Submit & Next Round →"
|
|
: "Submit & See Results →";
|
|
}
|
|
|
|
function tickTimer() {
|
|
timeLeft--;
|
|
updateTimerUI();
|
|
if (timeLeft <= 0) {
|
|
clearInterval(timerInterval);
|
|
submitRound(true); // auto-submit
|
|
}
|
|
}
|
|
|
|
function updateTimerUI() {
|
|
elTimerNum.textContent = timeLeft;
|
|
const pct = (timeLeft / ROUND_DURATION) * 100;
|
|
elTimerBar.style.width = pct + "%";
|
|
|
|
// Colour shift
|
|
if (timeLeft <= 10) {
|
|
elTimerBar.style.background = "#e05c5c";
|
|
elTimerNum.style.color = "#e05c5c";
|
|
} else if (timeLeft <= 20) {
|
|
elTimerBar.style.background = "#f0b429";
|
|
elTimerNum.style.color = "#f0b429";
|
|
} else {
|
|
elTimerBar.style.background = "";
|
|
elTimerNum.style.color = "";
|
|
}
|
|
}
|
|
|
|
function submitRound(auto = false) {
|
|
clearInterval(timerInterval);
|
|
elBtnSubmit.disabled = true;
|
|
|
|
const points = Drawing.getPoints();
|
|
const score = Scoring.calculateScore(points);
|
|
scores.push(score);
|
|
|
|
// Update sidebar score row
|
|
if (typeof window.updateScoreDisplay === "function") {
|
|
window.updateScoreDisplay(currentRound, score);
|
|
}
|
|
|
|
// Flash score feedback
|
|
showScoreFeedback(score);
|
|
|
|
const delay = auto ? 400 : 1200;
|
|
setTimeout(() => {
|
|
if (currentRound < TOTAL_ROUNDS - 1) {
|
|
currentRound++;
|
|
startRound();
|
|
} else {
|
|
finishGame();
|
|
}
|
|
}, delay);
|
|
}
|
|
|
|
function showScoreFeedback(score) {
|
|
const grade = Scoring.getGrade(score);
|
|
const el = document.getElementById("score-feedback");
|
|
el.textContent = `${score}% ${grade.label}`;
|
|
el.style.color = grade.color;
|
|
el.style.opacity = "1";
|
|
el.style.transform = "translateY(0)";
|
|
setTimeout(() => {
|
|
el.style.opacity = "0";
|
|
el.style.transform = "translateY(-10px)";
|
|
}, 900);
|
|
}
|
|
|
|
function finishGame() {
|
|
const totalScore = scores.reduce((a, b) => a + b, 0);
|
|
const state = {
|
|
currentRound: TOTAL_ROUNDS,
|
|
scores,
|
|
totalScore,
|
|
countries: roundCountries.map(c => c.name),
|
|
};
|
|
Storage.saveGameState(state);
|
|
|
|
// Save to leaderboard
|
|
Storage.saveLeaderboard({
|
|
name: Storage.getPlayerName(),
|
|
totalScore,
|
|
scores,
|
|
date: new Date().toISOString(),
|
|
});
|
|
|
|
location.href = "results.html";
|
|
}
|
|
|
|
// ── Events
|
|
elBtnClear.addEventListener("click", () => Drawing.clear());
|
|
elBtnSubmit.addEventListener("click", () => submitRound(false));
|
|
|
|
// ── Boot
|
|
window.addEventListener("DOMContentLoaded", initGame);
|