Update script.js

This commit is contained in:
5803025031 2025-11-30 22:01:30 -05:00
parent 4c353781b1
commit aa2166af12

231
script.js
View File

@ -1,72 +1,189 @@
const game = document.getElementById("game");
const movesText = document.getElementById("moves");
const scoreText = document.getElementById("score");
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const uiLayer = document.getElementById('ui-layer');
const finalScoreSpan = document.getElementById('final-score');
const inGameScore = document.getElementById('ingame-score');
const highScoreDisplay = document.getElementById('high-score-display');
// Setup UI Flexbox
uiLayer.style.display = 'none';
let moves = 0;
let score = 0;
let firstCard = null;
let lock = false;
let gameRunning = true;
let speed = 2;
let blockHeight = 35;
let initialWidth = 200;
let blocks = [];
let currentBlock = {};
let direction = 1;
let hue = 0;
let icons = ["🍎", "🍌", "🍇", "🍓", "🍒", "🍑", "🍍", "🥝"]; // 8 pairs
let cards = [...icons, ...icons];
cards.sort(() => Math.random() - 0.5);
function initGame() {
score = 0;
blocks = [];
speed = 3;
hue = Math.random() * 360;
cards.forEach(icon => {
const div = document.createElement("div");
div.className = "card";
div.dataset.icon = icon;
div.textContent = "?";
game.appendChild(div);
});
inGameScore.innerText = score;
game.querySelectorAll(".card").forEach(card => {
card.addEventListener("click", () => {
if(lock || card.classList.contains("open") || card.classList.contains("matched")) return;
// Base block
blocks.push({
x: (canvas.width - initialWidth) / 2,
y: canvas.height - 100,
width: initialWidth,
color: `hsl(${hue}, 100%, 50%)`
});
card.classList.add("open");
card.textContent = card.dataset.icon;
spawnBlock();
if(!firstCard){
firstCard = card;
// Perubahan: Jangan panggil draw() di sini jika ini reset,
// biarkan resetGame yang mengontrol loop
if(gameRunning) draw();
}
function spawnBlock() {
const prevBlock = blocks[blocks.length - 1];
hue += 10;
currentBlock = {
x: 0,
y: prevBlock.y - blockHeight,
width: prevBlock.width,
color: `hsl(${hue}, 100%, 50%)`
};
if (currentBlock.y < 150) {
blocks.forEach(b => b.y += blockHeight);
currentBlock.y += blockHeight;
}
}
function drawBackground() {
ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
ctx.lineWidth = 1;
for (let i = 0; i < canvas.width; i += 40) {
ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, canvas.height); ctx.stroke();
}
for (let i = 0; i < canvas.height; i += 40) {
ctx.beginPath(); ctx.moveTo(0, i); ctx.lineTo(canvas.width, i); ctx.stroke();
}
}
function draw() {
if (!gameRunning) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
currentBlock.x += speed * direction;
if (currentBlock.x + currentBlock.width > canvas.width || currentBlock.x < 0) {
direction *= -1;
}
ctx.shadowBlur = 20;
blocks.forEach(b => {
ctx.fillStyle = b.color;
ctx.shadowColor = b.color;
ctx.fillRect(b.x, b.y, b.width, blockHeight);
ctx.fillStyle = 'rgba(255,255,255,0.2)';
ctx.fillRect(b.x, b.y, b.width, 5);
});
ctx.fillStyle = currentBlock.color;
ctx.shadowColor = currentBlock.color;
ctx.fillRect(currentBlock.x, currentBlock.y, currentBlock.width, blockHeight);
ctx.fillStyle = 'rgba(255,255,255,0.4)';
ctx.fillRect(currentBlock.x, currentBlock.y, currentBlock.width, 5);
ctx.shadowBlur = 0;
requestAnimationFrame(draw);
}
function placeBlock() {
if (!gameRunning) return;
const prevBlock = blocks[blocks.length - 1];
let overlap = currentBlock.width - Math.abs(currentBlock.x - prevBlock.x);
if (overlap <= 0) {
gameOver();
return;
}
moves++;
movesText.textContent = moves;
lock = true;
if(firstCard.dataset.icon === card.dataset.icon){
score += 100;
scoreText.textContent = score;
firstCard.classList.add("matched");
card.classList.add("matched");
firstCard = null;
lock = false;
saveScore(score);
if (currentBlock.x < prevBlock.x) {
currentBlock.width = overlap;
currentBlock.x = prevBlock.x;
} else {
score -= 20;
scoreText.textContent = score;
setTimeout(() => {
firstCard.classList.remove("open");
firstCard.textContent = "?";
card.classList.remove("open");
card.textContent = "?";
firstCard = null;
lock = false;
}, 700);
currentBlock.width = overlap;
}
});
});
function saveScore(score){
fetch("save_score.php", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "score=" + score
blocks.push(currentBlock);
score++;
inGameScore.innerText = score;
speed += 0.15;
spawnBlock();
}
function gameOver() {
gameRunning = false;
uiLayer.style.display = 'flex';
finalScoreSpan.innerText = score;
saveScore(score);
}
// --- PERBAIKAN UTAMA ADA DI SINI ---
function resetGame() {
uiLayer.style.display = 'none';
// Matikan gameRunning sementara agar klik tombol tidak terbaca sebagai 'placeBlock'
gameRunning = false;
initGame();
// Beri jeda 300ms. Setelah tombol dilepas, baru game aktif.
setTimeout(() => {
gameRunning = true;
draw(); // Mulai loop animasi
}, 300);
}
// Input Handler yang lebih aman
document.body.onkeydown = (e) => {
if (e.code === 'Space') {
if (gameRunning) {
placeBlock();
} else if (uiLayer.style.display === 'flex') {
// Cegah spasi merestart terlalu cepat
resetGame();
}
}
};
document.body.onclick = (e) => {
// PENTING: Jika yang diklik adalah tombol atau bagian dari UI Layer, JANGAN jalankan game
if (e.target.closest('#ui-layer') || e.target.closest('.btn')) return;
if (gameRunning) placeBlock();
};
function saveScore(newScore) {
const formData = new FormData();
formData.append('score', newScore);
fetch('save_score.php', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => fetchHighScore());
}
function fetchHighScore() {
fetch('save_score.php?action=get')
.then(response => response.json())
.then(data => {
highScoreDisplay.innerText = data.high_score || "0";
});
}
// Start pertama kali
initGame();
// Paksa draw pertama kali
gameRunning = true;
draw();