Files
2025-04-13 16:26:35 +02:00

149 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app.js Central game logic and initialization for EmojiTrail
import { EMOJIS } from './emoji.js';
// Game state variables
let currentTrail = [];
let currentLevel = 1;
let selected = [];
let bestLevel = localStorage.getItem('bestLevel') || 1;
/**
* Starts a new game round, resetting state and displaying the trail and options.
*/
export function startGame() {
const levelDisplay = document.getElementById('level');
const messageDisplay = document.getElementById('message');
const trailBox = document.getElementById('trail');
const optionsBox = document.getElementById('options');
if (!levelDisplay || !messageDisplay || !trailBox || !optionsBox) return;
messageDisplay.textContent = '';
const trail = generateTrail(currentLevel);
currentTrail = trail;
selected = [];
levelDisplay.textContent = `Level ${currentLevel} (Best: ${bestLevel})`;
showTrail(trail);
setTimeout(() => {
trailBox.innerHTML = ''; // Clear trail for options display
showOptions(generateOptions(trail));
}, 2000);
}
// Initialize start button
const startBtn = document.getElementById('startBtn');
if (startBtn) {
startBtn.textContent = '🔄';
startBtn.addEventListener('click', startGame);
}
/**
* Generates a trail of random emojis based on the current level.
* @param {number} level - The current game level.
* @returns {string[]} Array of emojis.
*/
function generateTrail(level) {
const result = [];
for (let i = 0; i < level; i++) {
result.push(EMOJIS[Math.floor(Math.random() * EMOJIS.length)]);
}
return result;
}
/**
* Generates a shuffled array of 12 options, including trail emojis and distractors.
* @param {string[]} trail - The current trail of emojis.
* @returns {string[]} Shuffled array of options.
*/
function generateOptions(trail) {
const trailSet = new Set(trail);
const needed = 12 - trailSet.size;
const distractors = EMOJIS.filter(e => !trailSet.has(e));
const randomExtras = [];
while (randomExtras.length < needed) {
const candidate = distractors[Math.floor(Math.random() * distractors.length)];
if (!randomExtras.includes(candidate)) randomExtras.push(candidate);
}
const combined = [...trailSet, ...randomExtras];
return shuffle(combined);
}
/**
* Shuffles an array using the Fisher-Yates algorithm.
* @param {any[]} array - The array to shuffle.
* @returns {any[]} The shuffled array.
*/
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
/**
* Displays the trail of emojis in the DOM.
* @param {string[]} trail - The array of emojis to display.
*/
function showTrail(trail) {
const box = document.getElementById('trail');
if (!box) return;
box.innerHTML = ''; // Clear previous trail
trail.forEach(e => {
const span = document.createElement('span');
span.className = 'trail-emoji';
span.textContent = e;
box.appendChild(span);
});
}
/**
* Displays the grid of clickable emoji options.
* @param {string[]} options - The array of emojis to display as options.
*/
function showOptions(options) {
const grid = document.getElementById('options');
if (!grid) return;
grid.innerHTML = ''; // Clear previous options
options.forEach(e => {
const span = document.createElement('span');
span.textContent = e;
span.addEventListener('click', () => handlePick(e, span));
grid.appendChild(span);
});
}
/**
* Handles player selection of an emoji option.
* @param {string} emoji - The selected emoji.
* @param {HTMLElement} el - The DOM element clicked.
*/
function handlePick(emoji, el) {
el.classList.add('picked');
selected.push(emoji);
const messageDisplay = document.getElementById('message');
const levelDisplay = document.getElementById('level');
if (!messageDisplay || !levelDisplay) return;
if (selected.length === currentTrail.length) {
if (selected.every((e, i) => e === currentTrail[i])) {
messageDisplay.textContent = '✅ Correct! Level up!';
currentLevel++;
if (currentLevel > bestLevel) {
bestLevel = currentLevel;
localStorage.setItem('bestLevel', bestLevel);
}
} else {
messageDisplay.textContent = '❌ Wrong! Try again.';
}
setTimeout(() => {
startGame();
}, 1200);
}
}