From 2f29578cf20ae23d4c2c3e28772b8bb555ce4831 Mon Sep 17 00:00:00 2001 From: Nathan Date: Wed, 17 Dec 2025 15:34:22 +0700 Subject: [PATCH] adding score --- assets/gameboard-easy.css | 2 +- assets/gameboard-easy.js | 153 ++++++++++++++++++++++---------------- gameboard-easy.php | 2 +- mainboard.php | 2 +- score.php | 30 ++++++++ 5 files changed, 122 insertions(+), 67 deletions(-) create mode 100644 score.php diff --git a/assets/gameboard-easy.css b/assets/gameboard-easy.css index e8e03d9..dab58db 100644 --- a/assets/gameboard-easy.css +++ b/assets/gameboard-easy.css @@ -243,7 +243,7 @@ body { @media (max-width: 700px) { .gameboard { - grid-template-columns: repeat(2, 1fr); + grid-template-columns: repeat(3, 1fr); padding: 12px; gap: 10px; } diff --git a/assets/gameboard-easy.js b/assets/gameboard-easy.js index 37ce7a1..c1d6ae8 100644 --- a/assets/gameboard-easy.js +++ b/assets/gameboard-easy.js @@ -1,4 +1,4 @@ -// --- KONFIGURASI AUDIO & DOM --- +// --- AUDIO CONFIG --- const bgMusic = document.getElementById("bgMusic"); const sfxClick = document.getElementById("sfxClick"); const sfxMatch = document.getElementById("sfxMatch"); @@ -7,21 +7,26 @@ const sfxCountdown = document.getElementById("sfxCountdown"); const sfxWin = document.getElementById("sfxWin"); const sfxLose = document.getElementById("sfxLose"); const toggleBtn = document.getElementById("toggleMusic"); -const overlay = document.getElementById("countdown-overlay"); +const countdownOverlay = document.getElementById("countdown-overlay"); let musicMuted = true; -// AUTO-PLAY PADA INTERAKSI PERTAMA -function initAudio() { - if(musicMuted) { - bgMusic.play().catch(() => {}); - bgMusic.volume = 0.5; - toggleBtn.textContent = "🔊"; - musicMuted = false; - document.removeEventListener('click', initAudio); +function playSFX(audio) { + if(!musicMuted) { + audio.currentTime = 0; + audio.play().catch(() => {}); } } -document.addEventListener('click', initAudio); + +// 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(); @@ -35,17 +40,13 @@ toggleBtn.onclick = (e) => { musicMuted = !musicMuted; }; -function playSFX(audio) { - if(!musicMuted) { - audio.currentTime = 0; - audio.play().catch(() => {}); - } -} - -// --- LOGIKA GAME ASLI --- +// --- GAME LOGIC --- +// UBAHAN DISINI: Hanya pakai 6 Gambar (Fruit 1-6) +// 6 Gambar x 2 = 12 Kartu. +// Karena CSS kamu 4 kolom, maka otomatis jadi: 4 Samping x 3 Bawah. const images = [ - "images/fruit1.png", "images/fruit2.png", "images/fruit3.png", - "images/fruit4.png", "images/fruit5.png", "images/fruit6.png", + "images/fruit1.png", "images/fruit2.png", "images/fruit3.png", + "images/fruit4.png", "images/fruit5.png", "images/fruit6.png" ]; let cards = [...images, ...images]; @@ -56,33 +57,57 @@ let moves = 0; let score = 0; let countdown; let combo = 1; -let lastMatchTime = 0; let pendingMatch = false; +let lastMatchTime = 0; -function shuffleArray(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]]; +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 array; + return result; } function runCountdown(callback) { let count = 3; - overlay.style.display = "flex"; - overlay.innerHTML = `${count}`; + countdownOverlay.style.display = "flex"; + countdownOverlay.innerHTML = `${count}`; playSFX(sfxCountdown); let cdTimer = setInterval(() => { count--; if (count > 0) { - overlay.innerHTML = `${count}`; + countdownOverlay.innerHTML = `${count}`; playSFX(sfxCountdown); } else if (count === 0) { - overlay.innerHTML = `GO!`; + countdownOverlay.innerHTML = `GO!`; } else { clearInterval(cdTimer); - overlay.style.display = "none"; + countdownOverlay.style.display = "none"; callback(); } }, 1000); @@ -94,30 +119,29 @@ function startTimer() { document.getElementById("timer").textContent = --time; if (time <= 0) { clearInterval(countdown); - showEndScreen(false); // Kalah + showEndScreen(false); } }, 1000); } function showEndScreen(isWin) { - clearInterval(countdown); - bgMusic.pause(); + clearInterval(countdown); + bgMusic.pause(); + if(isWin) playSFX(sfxWin); else playSFX(sfxLose); - 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!"; - 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; - let baseScore = score; - let timeBonus = time * 5; - let moveBonus = Math.max(0, 200 - moves * 10); - let total = baseScore + timeBonus + moveBonus; - - document.getElementById("baseScoreEnd").textContent = baseScore; - document.getElementById("timeBonusEnd").textContent = "+" + (isWin ? timeBonus : 0); - document.getElementById("moveBonusEnd").textContent = "+" + (isWin ? moveBonus : 0); - document.getElementById("totalScoreEnd").textContent = isWin ? total : baseScore; - document.getElementById("endScreen").style.display = "flex"; + 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"; } function flipCard(card) { @@ -132,8 +156,8 @@ function flipCard(card) { if (flipped.length === 2) { moves++; document.getElementById("moves").textContent = moves; - let img1 = flipped[0].querySelector(".back img").src; - let img2 = flipped[1].querySelector(".back img").src; + let img1 = flipped[0].querySelector("img").src; + let img2 = flipped[1].querySelector("img").src; if (img1 === img2) { playSFX(sfxMatch); @@ -142,18 +166,20 @@ function flipCard(card) { else { if (now - lastMatchTime <= 3000) { combo++; - score += (10 * combo); - document.getElementById("score").textContent = score; - } else { combo = 1; } + 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), 600); + setTimeout(() => showEndScreen(true), 500); } } else { playSFX(sfxWrong); @@ -169,19 +195,18 @@ function startGame() { document.getElementById("endScreen").style.display = "none"; const board = document.getElementById("game-board"); board.innerHTML = ""; - + runCountdown(() => { - if(!musicMuted) bgMusic.play(); - const shuffledCards = shuffleArray([...cards]); - shuffledCards.forEach(image => { - const card = document.createElement("div"); - card.className = "card"; - card.innerHTML = `
?
`; - card.onclick = () => flipCard(card); - board.appendChild(card); + 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; - timerStarted = false; + pendingMatch = false; flipped = []; timerStarted = false; document.getElementById("timer").textContent = time; document.getElementById("moves").textContent = moves; document.getElementById("score").textContent = score; diff --git a/gameboard-easy.php b/gameboard-easy.php index 1bb2251..9387c0a 100644 --- a/gameboard-easy.php +++ b/gameboard-easy.php @@ -13,7 +13,7 @@ $user = $_SESSION['user']; -Memory Card Premium +Memory Card Premium 3x4 diff --git a/mainboard.php b/mainboard.php index 4fb4076..7a649aa 100644 --- a/mainboard.php +++ b/mainboard.php @@ -68,7 +68,7 @@ $roleIcon = ($roleRaw === 'admin') ? '👑' : '🎮'; diff --git a/score.php b/score.php new file mode 100644 index 0000000..15f55c9 --- /dev/null +++ b/score.php @@ -0,0 +1,30 @@ +prepare("INSERT INTO scores (user_id, score) VALUES (?, ?)"); + $stmt->bind_param("ii", $user_id, $score); + + if ($stmt->execute()) { + echo "Berhasil simpan skor untuk ID: " . $user_id; + } else { + echo "Gagal: " . $conn->error; + } +} else { + echo "Error: Belum login atau Data Session tidak sesuai."; +} +?> \ No newline at end of file