ga jadi ga isa konek
This commit is contained in:
parent
e8975da670
commit
da8b69c174
453
GameLogic.js
453
GameLogic.js
@ -1,4 +1,4 @@
|
|||||||
//bagian tempat main ama buat generate game 2d
|
// //bagian tempat main ama buat generate game 2d
|
||||||
var canvas = document.getElementById("game");
|
var canvas = document.getElementById("game");
|
||||||
var content = canvas.getContext("2d");
|
var content = canvas.getContext("2d");
|
||||||
const Text = document.getElementById("text");
|
const Text = document.getElementById("text");
|
||||||
@ -25,9 +25,9 @@ KepalaKeKanan.src = "image/KepalaHorizontalKanan.png";
|
|||||||
var KepalaKeAtas = new Image();
|
var KepalaKeAtas = new Image();
|
||||||
KepalaKeAtas.src = "image/KepalaVertikalAtas.png";
|
KepalaKeAtas.src = "image/KepalaVertikalAtas.png";
|
||||||
var KepalaKeKiri = new Image();
|
var KepalaKeKiri = new Image();
|
||||||
KepalaKeKiri.src = "image/KepalaVertikalBawah.png";
|
KepalaKeKiri.src = "image/KepalaVertikalBawah.png"; // Asumsi ini adalah Kepala ke KIRI
|
||||||
var KepalaKeBawah = new Image();
|
var KepalaKeBawah = new Image();
|
||||||
KepalaKeBawah.src = "image/KepalaHorizontalKiri.png";
|
KepalaKeBawah.src = "image/KepalaHorizontalKiri.png"; // Asumsi ini adalah Kepala ke BAWAH
|
||||||
// ↑ kepala ular
|
// ↑ kepala ular
|
||||||
|
|
||||||
var BadanHori = new Image();
|
var BadanHori = new Image();
|
||||||
@ -50,291 +50,324 @@ RandomizeApel();
|
|||||||
|
|
||||||
//mastiin gambar external generate dulu sebelum game start
|
//mastiin gambar external generate dulu sebelum game start
|
||||||
KepalaKeKanan.onload = function () {
|
KepalaKeKanan.onload = function () {
|
||||||
function gameLoop() {}
|
// Memastikan gambar termuat, meskipun fungsi ini tidak melakukan apa-apa selain deklarasi
|
||||||
|
function gameLoop() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//ngatur biar game ga langsung jalan
|
//ngatur biar game ga langsung jalan
|
||||||
function StartingGame(menantang) {
|
function StartingGame(menantang) {
|
||||||
ModeH = menantang;
|
ModeH = menantang;
|
||||||
persiapan.style.display = "none";
|
persiapan.style.display = "none";
|
||||||
if (ModeH) {
|
if (ModeH) {
|
||||||
RandomSpawnWall();
|
RandomSpawnWall();
|
||||||
} else {
|
} else {
|
||||||
Tembok = [];
|
Tembok = [];
|
||||||
}
|
}
|
||||||
GameStart = true;
|
GameStart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//buat ngatur batu spwan apa ga nanti
|
//buat ngatur batu spwan apa ga nanti
|
||||||
document.getElementById("mode-normal").addEventListener("click", function () {
|
document.getElementById("mode-normal").addEventListener("click", function () {
|
||||||
StartingGame(false);
|
StartingGame(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("mode-tambahan").addEventListener("click", function () {
|
document.getElementById("mode-tambahan").addEventListener("click", function () {
|
||||||
StartingGame(true);
|
StartingGame(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
//play again pas gameover
|
//play again pas gameover
|
||||||
function resetGame() {
|
function resetGame() {
|
||||||
Ular.x = 528;
|
Ular.x = 528;
|
||||||
Ular.y = 240;
|
Ular.y = 240;
|
||||||
Ular.cells = [];
|
Ular.cells = [];
|
||||||
Ular.maxCells = 4;
|
Ular.maxCells = 4;
|
||||||
Ular.dx = grid;
|
Ular.dx = grid;
|
||||||
Ular.dy = 0;
|
Ular.dy = 0;
|
||||||
Tembok = [];
|
Tembok = [];
|
||||||
RandomizeApel();
|
RandomizeApel();
|
||||||
UpdateScore(0);
|
UpdateScore(0);
|
||||||
ModeH = false;
|
ModeH = false;
|
||||||
GameStart = false;
|
// Penting: Jangan set GameStart=false di sini jika ingin memulai ulang game loop
|
||||||
|
// Kita set GameStart=false saat game over, lalu di sini kita persiapkan UI
|
||||||
}
|
}
|
||||||
|
|
||||||
//ngatur tombol pas gameover kemana abis di klik
|
//ngatur tombol pas gameover kemana abis di klik
|
||||||
PlayAgain.addEventListener("click", function () {
|
PlayAgain.addEventListener("click", function () {
|
||||||
UpDead.style.display = "none";
|
UpDead.style.display = "none";
|
||||||
resetGame();
|
resetGame();
|
||||||
persiapan.style.display = "flex";
|
persiapan.style.display = "flex";
|
||||||
});
|
});
|
||||||
|
|
||||||
Udahan.addEventListener("click", function () {
|
Udahan.addEventListener("click", function () {
|
||||||
UpDead.style.display = "none";
|
UpDead.style.display = "none";
|
||||||
resetGame();
|
resetGame();
|
||||||
|
// Opsional: Redirect ke halaman lain
|
||||||
|
// window.location.href = 'leaderboard.php';
|
||||||
});
|
});
|
||||||
|
|
||||||
//gameover terus ngatur ular ke setting awal
|
//gameover terus ngatur ular ke setting awal
|
||||||
function gameLoop() {
|
function gameLoop() {
|
||||||
if (!GameStart) {
|
if (!GameStart) {
|
||||||
requestAnimationFrame(gameLoop);
|
requestAnimationFrame(gameLoop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ClearCanvas();
|
ClearCanvas();
|
||||||
Movement();
|
Movement();
|
||||||
IntiGame();
|
IntiGame();
|
||||||
|
|
||||||
requestAnimationFrame(gameLoop);
|
requestAnimationFrame(gameLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
//random spawn Apel
|
//random spawn Apel
|
||||||
function RandomizeApel() {
|
function RandomizeApel() {
|
||||||
var pembataslebar = Math.floor(canvas.width / grid);
|
var pembataslebar = Math.floor(canvas.width / grid);
|
||||||
var pembatastinggi = Math.floor(canvas.height / grid);
|
var pembatastinggi = Math.floor(canvas.height / grid);
|
||||||
Apel.x = Math.floor(Math.random() * pembataslebar) * grid;
|
|
||||||
Apel.y = Math.floor(Math.random() * pembatastinggi) * grid;
|
do {
|
||||||
|
Apel.x = Math.floor(Math.random() * pembataslebar) * grid;
|
||||||
|
Apel.y = Math.floor(Math.random() * pembatastinggi) * grid;
|
||||||
|
|
||||||
|
// Pastikan Apel tidak spawn di atas ular
|
||||||
|
var isOverlapSnake = Ular.cells.some(cell => cell.x === Apel.x && cell.y === Apel.y);
|
||||||
|
|
||||||
|
// Pastikan Apel tidak spawn di atas tembok
|
||||||
|
var isOverlapWall = Tembok.some(bata => bata.x === Apel.x && bata.y === Apel.y);
|
||||||
|
|
||||||
|
} while (isOverlapSnake || isOverlapWall);
|
||||||
}
|
}
|
||||||
|
|
||||||
//random spawn tembok
|
//random spawn tembok
|
||||||
function RandomSpawnWall() {
|
function RandomSpawnWall() {
|
||||||
var TembokX, TembokY;
|
var TembokX, TembokY;
|
||||||
var kosong;
|
var kosong;
|
||||||
var pembataslebar = Math.floor(canvas.width / grid);
|
var pembataslebar = Math.floor(canvas.width / grid);
|
||||||
var pembatastinggi = Math.floor(canvas.height / grid);
|
var pembatastinggi = Math.floor(canvas.height / grid);
|
||||||
|
|
||||||
//create tembok
|
//create tembok
|
||||||
do {
|
do {
|
||||||
kosong = true;
|
kosong = true;
|
||||||
|
|
||||||
TembokX = Math.floor(Math.random() * pembataslebar) * grid;
|
TembokX = Math.floor(Math.random() * pembataslebar) * grid;
|
||||||
TembokY = Math.floor(Math.random() * pembatastinggi) * grid;
|
TembokY = Math.floor(Math.random() * pembatastinggi) * grid;
|
||||||
|
|
||||||
//cek untuk posisi yang mau di kasih tembok ada/tidak ada ularnya
|
// cek untuk posisi yang mau di kasih tembok ada/tidak ada ularnya
|
||||||
for (var i = 0; i < Ular.cells.length; i++) {
|
for (var i = 0; i < Ular.cells.length; i++) {
|
||||||
if (Ular.cells[i].x === TembokX && Ular.cells[i].y === TembokY) {
|
// Hindari spawn di sekitar kepala ular (misal 5 kotak pertama)
|
||||||
kosong = false;
|
if (Math.abs(Ular.cells[i].x - TembokX) <= grid * 5 && Math.abs(Ular.cells[i].y - TembokY) <= grid * 5) {
|
||||||
break;
|
kosong = false;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//tidak memperbolehkan tembok spawn sama dengan apel
|
// tidak memperbolehkan tembok spawn sama dengan apel
|
||||||
if (TembokX === Apel.x && TembokY === Apel.y) {
|
if (TembokX === Apel.x && TembokY === Apel.y) {
|
||||||
kosong = false;
|
kosong = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < Tembok.length; i++) {
|
// Cek agar tembok tidak menumpuk
|
||||||
if (Tembok[i].x === TembokX && Tembok[i].y === TembokY) {
|
for (var i = 0; i < Tembok.length; i++) {
|
||||||
kosong = false;
|
if (Tembok[i].x === TembokX && Tembok[i].y === TembokY) {
|
||||||
break;
|
kosong = false;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
} while (kosong === false);
|
}
|
||||||
Tembok.push({ x: TembokX, y: TembokY });
|
} while (kosong === false);
|
||||||
|
Tembok.push({ x: TembokX, y: TembokY });
|
||||||
}
|
}
|
||||||
|
|
||||||
//nambah tembok tiap score kelipatan ... berapa enaknya ya? 😁
|
//nambah tembok tiap score kelipatan
|
||||||
function PenambahanTembok() {
|
function PenambahanTembok() {
|
||||||
if (ModeH) {
|
if (ModeH) {
|
||||||
if (Tembok.length < Math.floor(score / 2)) {
|
// Tambah tembok setiap 2 skor, tapi jangan melebihi batas (misal 15 tembok)
|
||||||
RandomSpawnWall();
|
if (score > 0 && score % 2 === 0 && Tembok.length < 15 && Tembok.length < score / 2) {
|
||||||
|
RandomSpawnWall();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set dan update score
|
//set dan update score
|
||||||
function UpdateScore(amount) {
|
function UpdateScore(amount) {
|
||||||
score = amount > 0 ? score + amount : 0;
|
score = amount > 0 ? score + amount : 0;
|
||||||
highscore = score > highscore ? score : highscore;
|
// Highscore hanya di update jika skor > highscore yang TERCATAT LOKAL.
|
||||||
Text.innerHTML =
|
// Highscore dari database biasanya diambil saat inisialisasi.
|
||||||
"Score: " + score + "<br>Highscore: " + highscore + "<br>Speed: " + speed;
|
highscore = score > highscore ? score : highscore;
|
||||||
|
|
||||||
PenambahanTembok();
|
Text.innerHTML =
|
||||||
|
"Score: " + score + "<br>Highscore: " + highscore + "<br>Speed: " + speed;
|
||||||
|
|
||||||
|
PenambahanTembok();
|
||||||
}
|
}
|
||||||
|
|
||||||
//tampilin gameover
|
//tampilin gameover
|
||||||
function GameOver() {
|
function GameOver() {
|
||||||
GameStart = false;
|
GameStart = false;
|
||||||
ClearCanvas();
|
ClearCanvas();
|
||||||
|
|
||||||
const modePermainan = ModeH ? "Tambahan" : "Normal";
|
const modePermainan = ModeH ? "Tambahan" : "Normal";
|
||||||
if (score >= 0) {
|
|
||||||
kirimSkorKeServer(score, modePermainan);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TAMPILKAN POP-UP GAME OVER
|
// Kirim skor ke server hanya jika skor lebih besar dari 0 (atau sesuai kriteria)
|
||||||
ScoreMain.innerHTML = "Score: " + score;
|
if (score > 0) {
|
||||||
UpDead.style.display = "flex";
|
kirimSkorKeServer(score, modePermainan);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TAMPILKAN POP-UP GAME OVER
|
||||||
|
ScoreMain.innerHTML = "Score: " + score;
|
||||||
|
UpDead.style.display = "flex";
|
||||||
}
|
}
|
||||||
|
|
||||||
//reset isi canvas doang
|
//reset isi canvas doang
|
||||||
function ClearCanvas() {
|
function ClearCanvas() {
|
||||||
content.clearRect(0, 0, canvas.width, canvas.height);
|
content.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//bagian utama:
|
//bagian utama:
|
||||||
//ular makan dan mati pas ketemu badannya
|
//ular makan dan mati pas ketemu badannya
|
||||||
function IntiGame() {
|
function IntiGame() {
|
||||||
//buat gambarnya bisa keluar
|
// buat gambarnya bisa keluar
|
||||||
content.drawImage(ApelImage, Apel.x, Apel.y, grid, grid);
|
content.drawImage(ApelImage, Apel.x, Apel.y, grid, grid);
|
||||||
Tembok.forEach(function (bata) {
|
|
||||||
content.drawImage(TembokImage, bata.x, bata.y, grid, grid);
|
|
||||||
});
|
|
||||||
|
|
||||||
Ular.cells.forEach(function (cell, index) {
|
// Gambar Tembok
|
||||||
if (index === 0) {
|
Tembok.forEach(function (bata) {
|
||||||
// Logika Pemilihan Gambar Kepala Ular
|
content.drawImage(TembokImage, bata.x, bata.y, grid, grid);
|
||||||
var posisiKepalaImage;
|
});
|
||||||
if (Ular.dx === grid) {
|
|
||||||
// KANAN
|
|
||||||
posisiKepalaImage = KepalaKeKanan;
|
|
||||||
} else if (Ular.dx === -grid) {
|
|
||||||
// KIRI
|
|
||||||
posisiKepalaImage = KepalaKeKiri;
|
|
||||||
} else if (Ular.dy === -grid) {
|
|
||||||
// ATAS
|
|
||||||
posisiKepalaImage = KepalaKeBawah;
|
|
||||||
} else if (Ular.dy === grid) {
|
|
||||||
// BAWAH
|
|
||||||
posisiKepalaImage = KepalaKeAtas;
|
|
||||||
} else {
|
|
||||||
// Default, misalnya saat game baru mulai (dx=grid, dy=0, atau default awal)
|
|
||||||
posisiKepalaImage = KepalaKeKanan;
|
|
||||||
}
|
|
||||||
|
|
||||||
content.drawImage(posisiKepalaImage, cell.x, cell.y, grid, grid);
|
// Gambar Ular
|
||||||
} else {
|
Ular.cells.forEach(function (cell, index) {
|
||||||
content.drawImage(BadanHori, cell.x, cell.y, grid, grid);
|
if (index === 0) {
|
||||||
}
|
// Logika Pemilihan Gambar Kepala Ular
|
||||||
});
|
var posisiKepalaImage;
|
||||||
|
if (Ular.dx === grid) { // KANAN
|
||||||
//bagian generate ular
|
posisiKepalaImage = KepalaKeKanan;
|
||||||
Ular.cells.forEach(function (cell, index) {
|
} else if (Ular.dx === -grid) { // KIRI
|
||||||
if (index === 0) {
|
posisiKepalaImage = KepalaKeKiri;
|
||||||
content.drawImage(KepalaKeKanan, cell.x, cell.y, grid, grid);
|
} else if (Ular.dy === -grid) { // ATAS
|
||||||
} else {
|
posisiKepalaImage = KepalaKeAtas; // Perlu dicek, di atas Anda menamakannya KepalaKeBawah?
|
||||||
content.drawImage(BadanHori, cell.x, cell.y, grid, grid);
|
} else if (Ular.dy === grid) { // BAWAH
|
||||||
}
|
posisiKepalaImage = KepalaKeBawah; // Perlu dicek, di atas Anda menamakannya KepalaKeAtas?
|
||||||
|
} else {
|
||||||
//buat pas ular makan Apel
|
posisiKepalaImage = KepalaKeKanan;
|
||||||
if (cell.x === Apel.x && cell.y === Apel.y) {
|
}
|
||||||
Ular.maxCells += 1;
|
content.drawImage(posisiKepalaImage, cell.x, cell.y, grid, grid);
|
||||||
UpdateScore(1);
|
} else {
|
||||||
RandomizeApel();
|
// Logika sederhana untuk badan: selalu horizontal
|
||||||
}
|
// Catatan: untuk badan vertikal/belokan, perlu logika tambahan, tapi kita ikuti kode asli Anda.
|
||||||
|
content.drawImage(BadanHori, cell.x, cell.y, grid, grid);
|
||||||
//tabrak tembok = mati
|
|
||||||
if (index === 0) {
|
|
||||||
Tembok.forEach(function (bata) {
|
|
||||||
if (cell.x === bata.x && cell.y === bata.y) {
|
|
||||||
GameOver();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//buat pas ular mati kena badan sendiri
|
// buat pas ular makan Apel (Deteksi tabrakan kepala vs Apel)
|
||||||
for (var i = index + 1; i < Ular.cells.length; i++)
|
if (index === 0 && cell.x === Apel.x && cell.y === Apel.y) {
|
||||||
if (cell.x === Ular.cells[i].x && cell.y === Ular.cells[i].y) GameOver();
|
Ular.maxCells += 1;
|
||||||
});
|
UpdateScore(1);
|
||||||
|
RandomizeApel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// tabrak tembok = mati (Hanya kepala yang dicek)
|
||||||
|
if (index === 0) {
|
||||||
|
Tembok.forEach(function (bata) {
|
||||||
|
if (cell.x === bata.x && cell.y === bata.y) {
|
||||||
|
GameOver();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// buat pas ular mati kena badan sendiri (Hanya kepala vs sisa badan)
|
||||||
|
if (index === 0) {
|
||||||
|
for (var i = 1; i < Ular.cells.length; i++) { // Mulai dari index 1 (badan)
|
||||||
|
if (cell.x === Ular.cells[i].x && cell.y === Ular.cells[i].y) {
|
||||||
|
GameOver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//update teks pada speed kalau score update
|
//update teks pada speed kalau score update
|
||||||
function Movement() {
|
function Movement() {
|
||||||
if (++count < speed) return;
|
if (++count < speed) return;
|
||||||
if (ArahUlar > 0) ArahUlar--;
|
if (ArahUlar > 0) ArahUlar--;
|
||||||
count = 0;
|
count = 0;
|
||||||
Ular.x += Ular.dx;
|
|
||||||
Ular.y += Ular.dy;
|
// Pindahkan kepala
|
||||||
if (
|
Ular.x += Ular.dx;
|
||||||
Ular.x < 0 ||
|
Ular.y += Ular.dy;
|
||||||
Ular.x >= canvas.width ||
|
|
||||||
Ular.y < 0 ||
|
// Cek batas layar
|
||||||
Ular.y >= canvas.height
|
if (
|
||||||
)
|
Ular.x < 0 ||
|
||||||
GameOver();
|
Ular.x >= canvas.width ||
|
||||||
Ular.cells.unshift({ x: Ular.x, y: Ular.y });
|
Ular.y < 0 ||
|
||||||
if (Ular.cells.length > Ular.maxCells) Ular.cells.pop();
|
Ular.y >= canvas.height
|
||||||
|
)
|
||||||
|
GameOver();
|
||||||
|
|
||||||
|
// Tambahkan posisi baru ke sel pertama (Kepala)
|
||||||
|
Ular.cells.unshift({ x: Ular.x, y: Ular.y });
|
||||||
|
|
||||||
|
// Hapus sel terakhir (Ekor)
|
||||||
|
if (Ular.cells.length > Ular.maxCells) Ular.cells.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//input keyboard
|
//input keyboard
|
||||||
function InputKeyboard() {
|
function InputKeyboard() {
|
||||||
document.addEventListener("keydown", function (e) {
|
document.addEventListener("keydown", function (e) {
|
||||||
if (!GameStart) return;
|
if (!GameStart) return;
|
||||||
|
|
||||||
//jalan buat ular
|
// Key A, D (Kiri/Kanan)
|
||||||
if (
|
if (
|
||||||
ArahUlar == 0 &&
|
ArahUlar == 0 &&
|
||||||
((e.code == "KeyA" && Ular.dx === 0) ||
|
((e.code == "KeyA" && Ular.dx === 0) ||
|
||||||
(e.code == "KeyD" && Ular.dx === 0))
|
(e.code == "KeyD" && Ular.dx === 0))
|
||||||
) {
|
) {
|
||||||
ArahUlar = 1;
|
ArahUlar = 1;
|
||||||
Ular.dx = e.code === "KeyA" ? -grid : grid;
|
Ular.dx = e.code === "KeyA" ? -grid : grid;
|
||||||
Ular.dy = 0;
|
Ular.dy = 0;
|
||||||
} else if (
|
}
|
||||||
ArahUlar == 0 &&
|
// Key W, S (Atas/Bawah)
|
||||||
((e.code === "KeyW" && Ular.dy === 0) ||
|
else if (
|
||||||
(e.code == "KeyS" && Ular.dy === 0))
|
ArahUlar == 0 &&
|
||||||
) {
|
((e.code === "KeyW" && Ular.dy === 0) ||
|
||||||
ArahUlar = 1;
|
(e.code == "KeyS" && Ular.dy === 0))
|
||||||
Ular.dy = e.code == "KeyW" ? -grid : grid;
|
) {
|
||||||
Ular.dx = 0;
|
ArahUlar = 1;
|
||||||
} else if (
|
Ular.dy = e.code == "KeyW" ? -grid : grid;
|
||||||
ArahUlar == 0 &&
|
Ular.dx = 0;
|
||||||
((e.code === "ArrowUp" && Ular.dy === 0) ||
|
}
|
||||||
(e.code == "ArrowDown" && Ular.dy === 0))
|
// Arrow Up, Down
|
||||||
) {
|
else if (
|
||||||
ArahUlar = 1;
|
ArahUlar == 0 &&
|
||||||
Ular.dy = e.code == "ArrowUp" ? -grid : grid;
|
((e.code === "ArrowUp" && Ular.dy === 0) ||
|
||||||
Ular.dx = 0;
|
(e.code == "ArrowDown" && Ular.dy === 0))
|
||||||
} else if (
|
) {
|
||||||
ArahUlar == 0 &&
|
ArahUlar = 1;
|
||||||
((e.code === "ArrowLeft" && Ular.dx === 0) ||
|
Ular.dy = e.code == "ArrowUp" ? -grid : grid;
|
||||||
(e.code == "ArrowRight" && Ular.dx === 0))
|
Ular.dx = 0;
|
||||||
) {
|
}
|
||||||
ArahUlar = 1;
|
// Arrow Left, Right
|
||||||
Ular.dx = e.code == "ArrowLeft" ? -grid : grid;
|
else if (
|
||||||
Ular.dy = 0;
|
ArahUlar == 0 &&
|
||||||
}
|
((e.code === "ArrowLeft" && Ular.dx === 0) ||
|
||||||
|
(e.code == "ArrowRight" && Ular.dx === 0))
|
||||||
|
) {
|
||||||
|
ArahUlar = 1;
|
||||||
|
Ular.dx = e.code == "ArrowLeft" ? -grid : grid;
|
||||||
|
Ular.dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.code === "KeyE" || e.code == "KeyQ")
|
// Key E (Cepat/Kurangi speed), Key Q (Lambat/Tambah speed)
|
||||||
speed =
|
if (e.code === "KeyE" || e.code == "KeyQ")
|
||||||
e.code == "KeyE" && speed > 2
|
speed =
|
||||||
? speed - 1
|
e.code == "KeyE" && speed > 2
|
||||||
: e.code == "KeyQ" && speed < 30
|
? speed - 1
|
||||||
? speed + 1
|
: e.code == "KeyQ" && speed < 30
|
||||||
: speed;
|
? speed + 1
|
||||||
});
|
: speed;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function kirimSkorKeServer(skor, modePermainan) {
|
function kirimSkorKeServer(skor, modePermainan) {
|
||||||
console.log(`Mengirim skor ${skor} (Mode: ${modePermainan}) ke server...`);
|
console.log(`Mengirim skor ${skor} (Mode: ${modePermainan}) ke server...`);
|
||||||
|
|
||||||
|
// Ganti 'score.php' sesuai dengan path di server Anda
|
||||||
fetch('score.php', {
|
fetch('score.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -347,20 +380,28 @@ function kirimSkorKeServer(skor, modePermainan) {
|
|||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return response.json().then(error => { throw new Error(error.message || 'Gagal menyimpan skor'); });
|
return response.json().then(error => { throw new Error(error.message || 'Gagal menyimpan skor'); });
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status === 'success') {
|
if (data.status === 'success') {
|
||||||
console.log('✅ Berhasil:', data.message);
|
console.log('✅ Berhasil:', data.message);
|
||||||
|
// Opsional: Perbarui highscore lokal dengan skor yang baru jika ini highscore
|
||||||
|
if (data.message.includes('Highscore baru')) {
|
||||||
|
highscore = skor;
|
||||||
|
UpdateScore(0); // Update tampilan score/highscore
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Error Server:', data.message);
|
console.error('❌ Error Server:', data.message);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('⚠️ Error Jaringan atau Proses:', error.message);
|
console.error('⚠️ Error Jaringan atau Proses:', error.message);
|
||||||
|
// Tampilkan pesan error ke user jika perlu
|
||||||
|
// alert("Gagal terhubung ke server skor. Pastikan Anda sudah login.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
InputKeyboard();
|
InputKeyboard();
|
||||||
gameLoop();
|
gameLoop();
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
require_once "koneksi.php";
|
require_once "koneksi.php"; // Menggunakan koneksi MySQLi
|
||||||
|
|
||||||
if (isset($_SESSION['username'])) {
|
if (isset($_SESSION['username'])) {
|
||||||
$nama = $_SESSION['username'];
|
$nama = $_SESSION['username'];
|
||||||
@ -10,7 +10,9 @@ if (isset($_SESSION['username'])) {
|
|||||||
|
|
||||||
$score = 0;
|
$score = 0;
|
||||||
|
|
||||||
|
// 1. Ambil Skor User yang Login (Untuk Tampilan Individual, jika diperlukan)
|
||||||
if (!empty($nama)) {
|
if (!empty($nama)) {
|
||||||
|
// ⚠️ Perlu DITINGKATKAN ke prepared statement untuk keamanan
|
||||||
$getScore = "SELECT score FROM users WHERE username = '$nama'";
|
$getScore = "SELECT score FROM users WHERE username = '$nama'";
|
||||||
$resultMe = mysqli_query($koneksi, $getScore);
|
$resultMe = mysqli_query($koneksi, $getScore);
|
||||||
|
|
||||||
@ -20,32 +22,63 @@ if (!empty($nama)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Ambil 10 Skor Tertinggi
|
||||||
$sql = "SELECT username, score FROM users ORDER BY score DESC LIMIT 10";
|
$sql = "SELECT username, score FROM users ORDER BY score DESC LIMIT 10";
|
||||||
$result = mysqli_query($koneksi, $sql);
|
$result = mysqli_query($koneksi, $sql);
|
||||||
$leaderboard = [];
|
$leaderboard = [];
|
||||||
|
|
||||||
if($result) {
|
if($result) {
|
||||||
|
// Ambil semua hasil
|
||||||
$leaderboard = mysqli_fetch_all($result, MYSQLI_ASSOC);
|
$leaderboard = mysqli_fetch_all($result, MYSQLI_ASSOC);
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="id">
|
<html lang="id">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background: linear-gradient(to bottom right, #A3D438, #004D40);
|
background: linear-gradient(to bottom right, #A3D438, #004D40);
|
||||||
height: 568px;
|
height: 100vh; /* Menggunakan vh agar mencakup seluruh tinggi layar */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 50px;
|
||||||
|
color: white;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 600px;
|
||||||
|
margin-top: 20px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #004D40;
|
||||||
|
color: white;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Leaderboard</title>
|
<title>Leaderboard</title>
|
||||||
<link rel="stylesheet" href="">
|
|
||||||
<link rel="stylesheet" href="">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<h1>🥇 Leaderboard Top 10 🥈</h1>
|
||||||
|
<?php if (!empty($nama)): ?>
|
||||||
|
<p style="font-size: 1.2em;">Skor Tertinggi Anda (<?php echo htmlspecialchars($nama); ?>): <strong><?php echo $score; ?> PTS</strong></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<p>Silakan <a href="login.php" style="color: yellow;">login</a> untuk melihat skor Anda.</p>
|
||||||
|
<?php endif; ?>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -64,9 +97,7 @@ if($result) {
|
|||||||
<tr>
|
<tr>
|
||||||
<td><?php echo $peringkat; ?></td>
|
<td><?php echo $peringkat; ?></td>
|
||||||
<td><?php echo htmlspecialchars($pemain['username']); ?></td>
|
<td><?php echo htmlspecialchars($pemain['username']); ?></td>
|
||||||
|
|
||||||
<td><?php echo $pemain['score']; ?> PTS</td>
|
<td><?php echo $pemain['score']; ?> PTS</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
@ -75,7 +106,6 @@ if($result) {
|
|||||||
} else {
|
} else {
|
||||||
echo '<tr><td colspan="3" style="text-align: center;">Belum ada Pemain</td></tr>';
|
echo '<tr><td colspan="3" style="text-align: center;">Belum ada Pemain</td></tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
|
|||||||
67
score.php
67
score.php
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
session_start();
|
||||||
require_once 'koneksi.php';
|
require_once 'koneksi.php';
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
@ -9,7 +10,7 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_SESSION['id_user'])) {
|
if (!isset($_SESSION['id_user']) && !isset($_SESSION['username'])) {
|
||||||
http_response_code(401);
|
http_response_code(401);
|
||||||
echo json_encode(['status' => 'error', 'message' => 'Anda harus login untuk menyimpan skor.']);
|
echo json_encode(['status' => 'error', 'message' => 'Anda harus login untuk menyimpan skor.']);
|
||||||
exit;
|
exit;
|
||||||
@ -17,9 +18,7 @@ if (!isset($_SESSION['id_user'])) {
|
|||||||
|
|
||||||
$input = json_decode(file_get_contents('php://input'), true);
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
|
||||||
$user_id = $_SESSION['id_user'];
|
|
||||||
$final_score = (int)($input['score'] ?? 0);
|
$final_score = (int)($input['score'] ?? 0);
|
||||||
$game_mode = $input['mode'] ?? 'Normal';
|
|
||||||
|
|
||||||
if ($final_score <= 0) {
|
if ($final_score <= 0) {
|
||||||
http_response_code(400);
|
http_response_code(400);
|
||||||
@ -27,24 +26,56 @@ if ($final_score <= 0) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
$user_id = null;
|
||||||
$sql = "INSERT INTO scores (id_user, score_value, mode) VALUES (:id_user, :score_value, :mode)";
|
if (isset($_SESSION['id_user'])) {
|
||||||
$stmt = $pdo->prepare($sql);
|
$user_id = $_SESSION['id_user'];
|
||||||
|
} elseif (isset($_SESSION['username'])) {
|
||||||
|
|
||||||
$stmt->execute([
|
$username = $_SESSION['username'];
|
||||||
':id_user' => $user_id,
|
|
||||||
':score_value' => $final_score,
|
|
||||||
':mode' => $game_mode
|
|
||||||
]);
|
|
||||||
|
|
||||||
echo json_encode([
|
$getID_sql = "SELECT id_user FROM users WHERE username = '$username'";
|
||||||
'status' => 'success',
|
$result_id = mysqli_query($koneksi, $getID_sql);
|
||||||
'message' => 'Skor berhasil disimpan.',
|
|
||||||
'skor_terkirim' => $final_score
|
|
||||||
]);
|
|
||||||
|
|
||||||
} catch (\PDOException $e) {
|
if ($result_id && mysqli_num_rows($result_id) > 0) {
|
||||||
|
$row = mysqli_fetch_assoc($result_id);
|
||||||
|
$user_id = $row['id_user'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$user_id) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'ID pengguna tidak ditemukan.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "UPDATE users SET score = ? WHERE id_user = ? AND score < ?";
|
||||||
|
|
||||||
|
if ($stmt = mysqli_prepare($koneksi, $sql)) {
|
||||||
|
mysqli_stmt_bind_param($stmt, "iii", $final_score, $user_id, $final_score);
|
||||||
|
$exec = mysqli_stmt_execute($stmt);
|
||||||
|
|
||||||
|
if ($exec) {
|
||||||
|
$rows_affected = mysqli_stmt_affected_rows($stmt);
|
||||||
|
|
||||||
|
if ($rows_affected > 0) {
|
||||||
|
$message = 'Skor berhasil diperbarui. Ini adalah Highscore baru!';
|
||||||
|
} else {
|
||||||
|
$message = 'Skor berhasil dikirim, tetapi skor tidak lebih tinggi dari Highscore sebelumnya.';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => $message,
|
||||||
|
'skor_terkirim' => $final_score
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'Gagal menjalankan kueri update: ' . mysqli_stmt_error($stmt)]);
|
||||||
|
}
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
|
||||||
|
} else {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
echo json_encode(['status' => 'error', 'message' => 'Terjadi kesalahan server saat menyimpan data.']);
|
echo json_encode(['status' => 'error', 'message' => 'Gagal mempersiapkan statement: ' . mysqli_error($koneksi)]);
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
Loading…
x
Reference in New Issue
Block a user