Update 2025-04-13_16:26:34
This commit is contained in:
148
static/app.js
Normal file
148
static/app.js
Normal file
@ -0,0 +1,148 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user