- const IMG_BASE = "/sources/img/memory/";
- const T = (window.APP_LOCALE === 'en')
- ? {
- cardAlt: 'Memory Card',
- card: 'Card',
- muteMusic: 'Mute music',
- enableMusic: 'Enable music'
- }
- : {
- cardAlt: 'Carta de Memory',
- card: 'Carta',
- muteMusic: 'Silenciar música',
- enableMusic: 'Activar música'
- };
- const cardsData = [
- {
- id: 1,
- imgSrc: IMG_BASE + 'bluy1.png'
- },
- {
- id: 2,
- imgSrc: IMG_BASE + 'bluy2.png'
- },
- {
- id: 3,
- imgSrc: IMG_BASE + 'bluy3.png'
- },
- {
- id: 4,
- imgSrc: IMG_BASE + 'bluy4.png'
- },
- {
- id: 5,
- imgSrc: IMG_BASE + 'bluy5.png'
- },
- {
- id: 6,
- imgSrc: IMG_BASE + 'bluy6.png'
- },
- {
- id: 7,
- imgSrc: IMG_BASE + 'bluy7.png'
- },
- {
- id: 8,
- imgSrc: IMG_BASE + 'bluy8.png'
- }
- ];
- const memoryGame = document.querySelector('.memory-game');
- const startButton = document.getElementById('start-button');
- const backgroundMusic = document.getElementById('background-music');
- const volumeDownButton = document.getElementById('volume-down');
- const volumeUpButton = document.getElementById('volume-up');
- const muteButton = document.getElementById('mute-button');
- const muteIcon = document.getElementById('mute-icon');
- const volumeLevel = document.getElementById('volume-level');
- let hasFlippedCard = false;
- let lockBoard = false;
- let firstCard = null;
- let secondCard = null;
- let matchesFound = 0;
- let musicStarted = false;
- /* ================================
- MÚSICA
- ================================ */
- const savedVolume = localStorage.getItem('memoryMusicVolume');
- const savedMuted = localStorage.getItem('memoryMusicMuted');
- backgroundMusic.volume = savedVolume !== null
- ? Number(savedVolume)
- : 0.4;
- backgroundMusic.muted = savedMuted === 'true';
- function clampVolume(value) {
- return Math.min(
- 1,
- Math.max(0, value)
- );
- }
- function updateVolumeInterface() {
- const percentage = Math.round(
- backgroundMusic.volume * 100
- );
- volumeLevel.textContent = `${percentage}%`;
- if (
- backgroundMusic.muted ||
- backgroundMusic.volume === 0
- ) {
- muteIcon.className = 'fa-solid fa-volume-xmark';
- muteButton.classList.add('is-muted');
- muteButton.title = T.enableMusic;
- muteButton.setAttribute(
- 'aria-label',
- T.enableMusic
- );
- return;
- }
- muteButton.classList.remove('is-muted');
- muteButton.title = T.muteMusic;
- muteButton.setAttribute(
- 'aria-label',
- T.muteMusic
- );
- if (backgroundMusic.volume <= 0.35) {
- muteIcon.className = 'fa-solid fa-volume-low';
- } else {
- muteIcon.className = 'fa-solid fa-volume-high';
- }
- }
- async function startMusic() {
- if (musicStarted) {
- return;
- }
- try {
- await backgroundMusic.play();
- musicStarted = true;
- } catch (error) {
- /*
- * Los navegadores pueden bloquear la reproducción
- * automática hasta que exista interacción del usuario.
- */
- }
- }
- function setVolume(value) {
- const newVolume = clampVolume(value);
- backgroundMusic.volume = newVolume;
- if (newVolume > 0) {
- backgroundMusic.muted = false;
- }
- localStorage.setItem(
- 'memoryMusicVolume',
- String(newVolume)
- );
- localStorage.setItem(
- 'memoryMusicMuted',
- String(backgroundMusic.muted)
- );
- updateVolumeInterface();
- startMusic();
- }
- function decreaseVolume() {
- setVolume(
- backgroundMusic.volume - 0.1
- );
- }
- function increaseVolume() {
- setVolume(
- backgroundMusic.volume + 0.1
- );
- }
- function toggleMute() {
- backgroundMusic.muted = !backgroundMusic.muted;
- localStorage.setItem(
- 'memoryMusicMuted',
- String(backgroundMusic.muted)
- );
- updateVolumeInterface();
- if (!backgroundMusic.muted) {
- startMusic();
- }
- }
- volumeDownButton.addEventListener(
- 'click',
- decreaseVolume
- );
- volumeUpButton.addEventListener(
- 'click',
- increaseVolume
- );
- muteButton.addEventListener(
- 'click',
- toggleMute
- );
- /*
- * Intentamos iniciar la música al cargar.
- * Si el navegador bloquea el autoplay,
- * arrancará con la primera interacción.
- */
- startMusic();
- document.addEventListener(
- 'pointerdown',
- () => {
- startMusic();
- },
- {
- once: true
- }
- );
- updateVolumeInterface();
- /* ================================
- MEMORY
- ================================ */
- function createCard(cardData) {
- const card = document.createElement('div');
- card.classList.add('memory-card');
- card.dataset.id = cardData.id;
- const frontFace = document.createElement('img');
- frontFace.classList.add('front-face');
- frontFace.src = cardData.imgSrc;
- frontFace.alt = T.cardAlt;
- const backFace = document.createElement('img');
- backFace.classList.add('back-face');
- backFace.src = IMG_BASE + 'carta.png';
- backFace.alt = `${T.card} ${cardData.id}`;
- card.appendChild(frontFace);
- card.appendChild(backFace);
- card.addEventListener(
- 'click',
- flipCard
- );
- memoryGame.appendChild(card);
- }
- function flipCard() {
- startMusic();
- if (lockBoard) {
- return;
- }
- if (this === firstCard) {
- return;
- }
- this.classList.add('flip');
- if (!hasFlippedCard) {
- hasFlippedCard = true;
- firstCard = this;
- return;
- }
- secondCard = this;
- checkForMatch();
- }
- function checkForMatch() {
- const isMatch =
- firstCard.dataset.id ===
- secondCard.dataset.id;
- if (isMatch) {
- disableCards();
- } else {
- unflipCards();
- }
- }
- function disableCards() {
- firstCard.removeEventListener(
- 'click',
- flipCard
- );
- secondCard.removeEventListener(
- 'click',
- flipCard
- );
- matchesFound++;
- if (matchesFound === cardsData.length) {
- showStartButton();
- }
- resetBoard();
- }
- function unflipCards() {
- lockBoard = true;
- setTimeout(
- () => {
- firstCard.classList.remove('flip');
- secondCard.classList.remove('flip');
- resetBoard();
- },
- 1000
- );
- }
- function resetBoard() {
- hasFlippedCard = false;
- lockBoard = false;
- firstCard = null;
- secondCard = null;
- }
- function initializeGame() {
- memoryGame.innerHTML = '';
- matchesFound = 0;
- startButton.style.display = 'none';
- const cards = [
- ...cardsData,
- ...cardsData
- ];
- for (
- let i = cards.length - 1;
- i > 0;
- i--
- ) {
- const j = Math.floor(
- Math.random() * (i + 1)
- );
- [
- cards[i],
- cards[j]
- ] = [
- cards[j],
- cards[i]
- ];
- }
- cards.forEach(
- cardData => {
- createCard(cardData);
- }
- );
- }
- function showStartButton() {
- startButton.style.display = 'flex';
- }
- startButton.addEventListener(
- 'click',
- initializeGame
- );
- initializeGame();