// --- AUDIO CONFIG --- const bgMusic = document.getElementById("bgMusic"); const sfxClick = document.getElementById("sfxClick"); const sfxMatch = document.getElementById("sfxMatch"); const sfxWrong = document.getElementById("sfxWrong"); const sfxCountdown = document.getElementById("sfxCountdown"); const sfxWin = document.getElementById("sfxWin"); const sfxLose = document.getElementById("sfxLose"); const toggleBtn = document.getElementById("toggleMusic"); const countdownOverlay = document.getElementById("countdown-overlay"); let musicMuted = true; function playSFX(audio) { if(!musicMuted) { audio.currentTime = 0; audio.play().catch(() => {}); } } // Interaksi pertama untuk aktifkan suara document.addEventListener('click', function initAudio() { if(musicMuted) { musicMuted = false; toggleBtn.textContent = "🔊"; bgMusic.play().catch(() => {}); document.removeEventListener('click', initAudio); } }); toggleBtn.onclick = (e) => { e.stopPropagation(); if (musicMuted) { bgMusic.play(); toggleBtn.textContent = "🔊"; } else { bgMusic.pause(); toggleBtn.textContent = "🔇"; } musicMuted = !musicMuted; }; const images = [ "images/fruit1.png", "images/fruit2.png", "images/fruit3.png", "images/fruit4.png", "images/fruit5.png", "images/fruit6.png" ]; let cards = [...images, ...images]; let flipped = []; let timerStarted = false; let time = 60; let moves = 0; let score = 0; let countdown; let combo = 1; let pendingMatch = false; let lastMatchTime = 0; function showComboPopup(targetCard, combo, bonus) { const popup = document.createElement("div"); popup.className = "combo-popup"; popup.innerHTML = `COMBO X${combo}
+${bonus} Bonus`; const rect = targetCard.getBoundingClientRect(); popup.style.left = rect.left + rect.width / 2 + "px"; popup.style.top = rect.top + "px"; popup.style.position = "fixed"; document.body.appendChild(popup); setTimeout(() => popup.remove(), 1500); } function shuffleDistant(cards, minDistance = 4) { let valid = false; let result; while (!valid) { result = [...cards].sort(() => Math.random() - 0.5); valid = true; const checked = new Set(); for (let i = 0; i < result.length; i++) { const value = result[i]; if (checked.has(value)) continue; checked.add(value); const firstIndex = result.indexOf(value); const lastIndex = result.lastIndexOf(value); const distance = Math.abs(lastIndex - firstIndex); if (distance < minDistance) { valid = false; break; } } } return result; } function runCountdown(callback) { let count = 3; countdownOverlay.style.display = "flex"; countdownOverlay.innerHTML = `${count}`; playSFX(sfxCountdown); let cdTimer = setInterval(() => { count--; if (count > 0) { countdownOverlay.innerHTML = `${count}`; playSFX(sfxCountdown); } else if (count === 0) { countdownOverlay.innerHTML = `GO!`; } else { clearInterval(cdTimer); countdownOverlay.style.display = "none"; callback(); } }, 1000); } function startTimer() { timerStarted = true; countdown = setInterval(() => { document.getElementById("timer").textContent = --time; if (time <= 0) { clearInterval(countdown); showEndScreen(false); } }, 1000); } function showEndScreen(isWin) { clearInterval(countdown); bgMusic.pause(); if(isWin) playSFX(sfxWin); else playSFX(sfxLose); document.getElementById("endTitle").textContent = isWin ? "🎉 Selamat!" : "⏰ Waktu Habis!"; document.getElementById("endMsg").textContent = isWin ? "Anda berhasil menyelesaikan permainan!" : "Coba lagi lain kali!"; let baseScore = score; let timeBonus = isWin ? time * 5 : 0; let moveBonus = isWin ? Math.max(0, 200 - moves * 10) : 0; let total = baseScore + timeBonus + moveBonus; document.getElementById("baseScoreEnd").textContent = baseScore; document.getElementById("timeBonusEnd").textContent = "+" + timeBonus; document.getElementById("moveBonusEnd").textContent = "+" + moveBonus; document.getElementById("totalScoreEnd").textContent = total; document.getElementById("endScreen").style.display = "flex"; if (isWin) { let formData = new FormData(); formData.append('score', total); formData.append('difficulty', 'Easy'); fetch('score.php', { method: 'POST', body: formData }) .then(response => response.text()) .then(result => console.log("Status Database: " + result)) .catch(error => console.error('Error:', error)); } } function flipCard(card) { if (!timerStarted) startTimer(); if (flipped.length === 2 || card.classList.contains("matched") || card.classList.contains("flipped")) return; playSFX(sfxClick); card.classList.add("flipped"); flipped.push(card); if (flipped.length === 2) { moves++; document.getElementById("moves").textContent = moves; let img1 = flipped[0].querySelector("img").src; let img2 = flipped[1].querySelector("img").src; if (img1 === img2) { playSFX(sfxMatch); const now = Date.now(); if (!pendingMatch) { pendingMatch = true; combo = 1; } else { if (now - lastMatchTime <= 3000) { combo++; let comboBonus = combo * 10; score += comboBonus; showComboPopup(flipped[0], combo, comboBonus); } else combo = 1; } lastMatchTime = now; flipped.forEach(c => c.classList.add("matched")); score += 50; document.getElementById("score").textContent = score; time += 5; document.getElementById("timer").textContent = time; flipped = []; if (document.querySelectorAll(".matched").length === cards.length) { setTimeout(() => showEndScreen(true), 500); } } else { playSFX(sfxWrong); setTimeout(() => { flipped.forEach(c => c.classList.remove("flipped")); flipped = []; }, 800); } } } function startGame() { document.getElementById("endScreen").style.display = "none"; const board = document.getElementById("game-board"); board.innerHTML = ""; runCountdown(() => { if(!musicMuted) bgMusic.play().catch(() => {}); shuffleDistant(cards, 4).forEach(image => { const card = document.createElement("div"); card.className = "card"; card.innerHTML = `
?
`; card.onclick = () => flipCard(card); board.appendChild(card); }); time = 60; moves = 0; score = 0; combo = 1; pendingMatch = false; flipped = []; timerStarted = false; document.getElementById("timer").textContent = time; document.getElementById("moves").textContent = moves; document.getElementById("score").textContent = score; }); } startGame();