503 lines
16 KiB
JavaScript
503 lines
16 KiB
JavaScript
// //bagian tempat main ama buat generate game 2d
|
||
var canvas = document.getElementById("game");
|
||
var content = canvas.getContext("2d");
|
||
const Text = document.getElementById("text");
|
||
const UpDead = document.getElementById("gameover-overlay");
|
||
const ScoreMain = document.getElementById("gameover-score");
|
||
const PlayAgain = document.getElementById("ulangi");
|
||
const Udahan = document.getElementById("keluar");
|
||
|
||
//settingan awal
|
||
var grid = 24;
|
||
var count = 0;
|
||
var speed = 10;
|
||
var score = 0;
|
||
var highscore = 0;
|
||
var ArahUlar = 0;
|
||
var GameOverTimer = 0;
|
||
var GameStart = false;
|
||
var ModeH = false;
|
||
const persiapan = document.getElementById("start");
|
||
|
||
//generate gambar external
|
||
|
||
//kepala
|
||
const kepala = {
|
||
kanan: new Image(),
|
||
kiri: new Image(),
|
||
atas: new Image(),
|
||
bawah: new Image(),
|
||
};
|
||
kepala.kanan.src = "image/KepalaHorizontalKanan.png";
|
||
kepala.kiri.src = "image/KepalaHorizontalKiri.png";
|
||
kepala.atas.src = "image/KepalaVertikalAtas.png";
|
||
kepala.bawah.src = "image/KepalaVertikalBawah.png";
|
||
|
||
//badan
|
||
const badan = {
|
||
horizontal: new Image(),
|
||
vertical: new Image(),
|
||
};
|
||
badan.horizontal.src = "image/BadanHorizontal.png";
|
||
badan.vertical.src = "image/BadanVertikal.png";
|
||
|
||
//const beluk
|
||
const belok = {
|
||
AtasKanan: new Image(),
|
||
AtasKiri: new Image(),
|
||
BawahKanan: new Image(),
|
||
BawahKiri: new Image(),
|
||
};
|
||
belok.AtasKanan.src = "image/BelokAtasKanan.png";
|
||
belok.AtasKiri.src = "image/BelokAtasKiri.png";
|
||
belok.BawahKanan.src = "image/BelokBawahKanan.png";
|
||
belok.BawahKiri.src = "image/BelokBawahKiri.png";
|
||
|
||
//bokong
|
||
const bokong = {
|
||
kanan: new Image(),
|
||
kiri: new Image(),
|
||
atas: new Image(),
|
||
bawah: new Image(),
|
||
};
|
||
bokong.kanan.src = "image/BokongHorizontalKanan.png";
|
||
bokong.kiri.src = "image/BokongHorizontalKiri.png";
|
||
bokong.atas.src = "image/BokongVertikalAtas.png";
|
||
bokong.bawah.src = "image/BokongVertikalBawah.png";
|
||
|
||
|
||
var ApelImage = new Image();
|
||
ApelImage.src = "image/ApelLayer.png";
|
||
var TembokImage = new Image();
|
||
TembokImage.src = "image/Tembok.png";
|
||
|
||
//set posisi ular dan Apel
|
||
var Ular = { x: 528, y: 240, dx: grid, dy: 0, cells: [], maxCells: 4 };
|
||
var Apel = { x: 0, y: 0 };
|
||
var Tembok = [];
|
||
UpdateScore(0);
|
||
RandomizeApel();
|
||
|
||
//buat ngatur batu spwan apa ga nanti
|
||
const halaman = document.querySelector(".HalamanFull");
|
||
const gameCanvas = document.getElementById("game");
|
||
|
||
document.getElementById("mode-normal").addEventListener("click", function () {
|
||
halaman.style.backgroundImage ='url("halamanFull/cherryBlossom.png")';
|
||
halaman.style.setProperty("--overlay-opacity", "0.4");
|
||
gameCanvas.style.filter = "brightness(1)";
|
||
|
||
StartingGame(false);
|
||
});
|
||
|
||
document.getElementById("mode-tambahan").addEventListener("click", function () {
|
||
halaman.style.backgroundImage ='url("halamanFull/cherryBlossomNight.png")';
|
||
halaman.style.setProperty("--overlay-opacity", "0.7");
|
||
gameCanvas.style.filter = "brightness(0.5)";
|
||
|
||
StartingGame(true);
|
||
});
|
||
|
||
|
||
|
||
function getDirection(cell1, cell2) {
|
||
if (cell2.x > cell1.x) return "kanan";
|
||
if (cell2.x < cell1.x) return "kiri";
|
||
if (cell2.y > cell1.y) return "bawah";
|
||
if (cell2.y < cell1.y) return "atas";
|
||
return null;
|
||
}
|
||
|
||
//ngatur biar game ga langsung jalan
|
||
function StartingGame(menantang) {
|
||
ModeH = menantang;
|
||
persiapan.style.display = "none";
|
||
if (ModeH) {
|
||
RandomSpawnWall();
|
||
} else {
|
||
Tembok = [];
|
||
}
|
||
GameStart = true;
|
||
}
|
||
|
||
//buat ngatur batu spwan apa ga nanti
|
||
document.getElementById("mode-normal").addEventListener("click", function () {
|
||
StartingGame(false);
|
||
});
|
||
|
||
document.getElementById("mode-tambahan").addEventListener("click", function () {
|
||
StartingGame(true);
|
||
});
|
||
|
||
//play again pas gameover
|
||
function resetGame() {
|
||
Ular.x = 528;
|
||
Ular.y = 240;
|
||
Ular.cells = [];
|
||
Ular.maxCells = 4;
|
||
Ular.dx = grid;
|
||
Ular.dy = 0;
|
||
Tembok = [];
|
||
RandomizeApel();
|
||
UpdateScore(0);
|
||
}
|
||
|
||
//ngatur tombol pas gameover kemana abis di klik
|
||
PlayAgain.addEventListener("click", function () {
|
||
UpDead.style.display = "none";
|
||
resetGame();
|
||
ModeH = false;
|
||
persiapan.style.display = "flex";
|
||
});
|
||
|
||
Udahan.addEventListener("click", function () {
|
||
UpDead.style.display = "none";
|
||
resetGame();
|
||
ModeH = false;
|
||
});
|
||
|
||
//gameover terus ngatur ular ke setting awal
|
||
function gameLoop() {
|
||
if (!GameStart) {
|
||
requestAnimationFrame(gameLoop);
|
||
return;
|
||
}
|
||
ClearCanvas();
|
||
Movement();
|
||
IntiGame();
|
||
|
||
requestAnimationFrame(gameLoop);
|
||
}
|
||
|
||
//random spawn Apel
|
||
function RandomizeApel() {
|
||
var pembataslebar = Math.floor(canvas.width / grid);
|
||
var pembatastinggi = Math.floor(canvas.height / grid);
|
||
|
||
do {
|
||
Apel.x = Math.floor(Math.random() * pembataslebar) * grid;
|
||
Apel.y = Math.floor(Math.random() * pembatastinggi) * grid;
|
||
|
||
//mastiin Apel gak spawn di atas ular
|
||
var isOverlapSnake = Ular.cells.some(cell => cell.x === Apel.x && cell.y === Apel.y);
|
||
|
||
//mastiin Apel gak spawn di atas tembok
|
||
var isOverlapWall = Tembok.some(bata => bata.x === Apel.x && bata.y === Apel.y);
|
||
|
||
} while (isOverlapSnake || isOverlapWall);
|
||
}
|
||
|
||
//random spawn tembok
|
||
function RandomSpawnWall() {
|
||
var TembokX, TembokY;
|
||
var kosong;
|
||
var pembataslebar = Math.floor(canvas.width / grid);
|
||
var pembatastinggi = Math.floor(canvas.height / grid);
|
||
|
||
//create tembok
|
||
do {
|
||
kosong = true;
|
||
|
||
TembokX = Math.floor(Math.random() * pembataslebar) * grid;
|
||
TembokY = Math.floor(Math.random() * pembatastinggi) * grid;
|
||
|
||
//cek untuk posisi yang mau di kasih tembok ada/tidak ada ularnya
|
||
for (var i = 0; i < Ular.cells.length; i++) {
|
||
if (Math.abs(Ular.cells[i].x - TembokX) <= grid * 5 && Math.abs(Ular.cells[i].y - TembokY) <= grid * 5) {
|
||
kosong = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// tidak memperbolehkan tembok spawn sama dengan apel
|
||
if (TembokX === Apel.x && TembokY === Apel.y) {
|
||
kosong = false;
|
||
}
|
||
|
||
//cek agar tembok tidak menumpuk
|
||
for (var i = 0; i < Tembok.length; i++) {
|
||
if (Tembok[i].x === TembokX && Tembok[i].y === TembokY) {
|
||
kosong = false;
|
||
break;
|
||
}
|
||
}
|
||
} while (kosong === false);
|
||
Tembok.push({ x: TembokX, y: TembokY });
|
||
}
|
||
|
||
//nambah tembok tiap score kelipatan
|
||
function PenambahanTembok() {
|
||
if (ModeH) {
|
||
if (score > 0 && score % 2 === 0 && Tembok.length < 15 && Tembok.length < score / 2) {
|
||
RandomSpawnWall();
|
||
}
|
||
}
|
||
}
|
||
|
||
//set dan update score
|
||
function UpdateScore(amount) {
|
||
score = amount > 0 ? score + amount : 0;
|
||
console.log("UPDATE SCORE , score:",score);
|
||
highscore = score > highscore ? score : highscore;
|
||
Text.innerHTML =
|
||
"Score: " +
|
||
score +
|
||
"<br>Highscore: " +
|
||
highscore +
|
||
"<br>Speed: " +
|
||
speed;
|
||
|
||
PenambahanTembok();
|
||
}
|
||
|
||
//tampilin gameover
|
||
function GameOver() {
|
||
GameStart = false;
|
||
ClearCanvas();
|
||
|
||
// Simpan score ke database
|
||
saveScore(score);
|
||
|
||
// TAMPILKAN POP-UP GAME OVER
|
||
ScoreMain.innerHTML = "Score: " + score;
|
||
UpDead.style.display = "flex";
|
||
}
|
||
|
||
//fungsi untuk menyimpan score ke database
|
||
function saveScore(finalScore) {
|
||
console.log("SAVING SCORE , score:",finalScore);
|
||
// Buat form tersembunyi untuk submit score
|
||
var form = document.createElement('form');
|
||
form.method = 'POST';
|
||
form.action = 'simpan_score.php';
|
||
form.style.display = 'none';
|
||
|
||
var scoreInput = document.createElement('input');
|
||
scoreInput.type = 'hidden';
|
||
scoreInput.name = 'score';
|
||
scoreInput.value = finalScore;
|
||
|
||
form.appendChild(scoreInput);
|
||
document.body.appendChild(form);
|
||
form.submit();
|
||
}
|
||
|
||
//reset isi canvas doang
|
||
function ClearCanvas() {
|
||
content.clearRect(0, 0, canvas.width, canvas.height);
|
||
}
|
||
|
||
//bagian utama:
|
||
//ular makan dan mati pas ketemu badannya
|
||
function IntiGame() {
|
||
// buat gambarnya bisa keluar
|
||
content.drawImage(ApelImage, Apel.x, Apel.y, grid, grid);
|
||
|
||
// Gambar Tembok
|
||
Tembok.forEach(function (bata) {
|
||
content.drawImage(TembokImage, bata.x, bata.y, grid, grid);
|
||
});
|
||
|
||
// Gambar Ular
|
||
Ular.cells.forEach(function (cell, index) {
|
||
var gambarUlar = null;
|
||
//pala ulo
|
||
if (index === 0) {
|
||
if (Ular.dx === grid) gambarUlar = kepala.kanan;
|
||
else if (Ular.dx === -grid) gambarUlar = kepala.kiri;
|
||
else if (Ular.dy === -grid) gambarUlar = kepala.atas;
|
||
else if (Ular.dy === grid) gambarUlar = kepala.bawah;
|
||
}
|
||
|
||
//bokong
|
||
else if (index === Ular.cells.length - 1) {
|
||
var sebelum = Ular.cells[index - 1];
|
||
var arahEkor = getDirection(sebelum, cell);
|
||
|
||
if (arahEkor === "kanan") gambarUlar = bokong.kanan;
|
||
else if (arahEkor === "kiri") gambarUlar = bokong.kiri;
|
||
else if (arahEkor === "atas") gambarUlar = bokong.atas;
|
||
else if (arahEkor === "bawah") gambarUlar = bokong.bawah;
|
||
}
|
||
|
||
//badan
|
||
else {
|
||
var sebelum = Ular.cells[index - 1];
|
||
var sesudah = Ular.cells[index + 1];
|
||
|
||
var ArahMasuk = getDirection(sebelum, cell);
|
||
var ArahKeluar = getDirection(cell, sesudah);
|
||
|
||
if (ArahMasuk && ArahKeluar) {
|
||
if (ArahMasuk === ArahKeluar) {
|
||
// Badan Lurus (Horizontal/Vertical)
|
||
if (ArahMasuk === "kiri" || ArahMasuk === "kanan") {
|
||
gambarUlar = badan.horizontal;
|
||
} else {
|
||
gambarUlar = badan.vertical;
|
||
}
|
||
}
|
||
|
||
else {
|
||
// belok AtasKanan
|
||
if ((ArahMasuk === "bawah" && ArahKeluar === "kanan") || (ArahMasuk === "kiri" && ArahKeluar === "atas"))
|
||
gambarUlar = belok.AtasKanan;
|
||
|
||
// belok AtasKiri
|
||
else if ((ArahMasuk === "bawah" && ArahKeluar === "kiri") || (ArahMasuk === "kanan" && ArahKeluar === "atas"))
|
||
gambarUlar = belok.AtasKiri;
|
||
|
||
// belok BawahKanan
|
||
else if ((ArahMasuk === "atas" && ArahKeluar === "kanan") || (ArahMasuk === "kiri" && ArahKeluar === "bawah"))
|
||
gambarUlar = belok.BawahKanan;
|
||
|
||
// belok BawahKiri
|
||
else if ((ArahMasuk === "atas" && ArahKeluar === "kiri") || (ArahMasuk === "kanan" && ArahKeluar === "bawah"))
|
||
gambarUlar = belok.BawahKiri;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (gambarUlar) {
|
||
content.drawImage(gambarUlar, cell.x, cell.y, grid, grid);
|
||
}
|
||
|
||
//ular makan apel
|
||
if (index === 0) {
|
||
if (cell.x === Apel.x && cell.y === Apel.y) {
|
||
Ular.maxCells += 1;
|
||
UpdateScore(1);
|
||
RandomizeApel();
|
||
}
|
||
|
||
//nabrak tembok
|
||
Tembok.forEach(function (bata) {
|
||
if (cell.x === bata.x && cell.y === bata.y) {
|
||
GameOver();
|
||
}
|
||
});
|
||
|
||
//nabrak diri e dw
|
||
for (var i = 1; i < Ular.cells.length; i++) {
|
||
if (cell.x === Ular.cells[i].x && cell.y === Ular.cells[i].y) {
|
||
GameOver();
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
//update speed kalau score update
|
||
function Movement() {
|
||
if (++count < speed) return;
|
||
if (ArahUlar > 0) ArahUlar--;
|
||
count = 0;
|
||
|
||
Ular.x += Ular.dx;
|
||
Ular.y += Ular.dy;
|
||
|
||
if (
|
||
Ular.x < 0 ||
|
||
Ular.x >= canvas.width ||
|
||
Ular.y < 0 ||
|
||
Ular.y >= canvas.height
|
||
)
|
||
GameOver();
|
||
|
||
Ular.cells.unshift({ x: Ular.x, y: Ular.y });
|
||
|
||
if (Ular.cells.length > Ular.maxCells) Ular.cells.pop();
|
||
}
|
||
|
||
//input keyboard
|
||
function InputKeyboard() {
|
||
document.addEventListener("keydown", function (e) {
|
||
if (!GameStart) return;
|
||
|
||
if (
|
||
ArahUlar == 0 &&
|
||
((e.code == "KeyA" && Ular.dx === 0) ||
|
||
(e.code == "KeyD" && Ular.dx === 0))
|
||
) {
|
||
ArahUlar = 1;
|
||
Ular.dx = e.code === "KeyA" ? -grid : grid;
|
||
Ular.dy = 0;
|
||
}
|
||
|
||
else if (
|
||
ArahUlar == 0 &&
|
||
((e.code === "KeyW" && Ular.dy === 0) ||
|
||
(e.code == "KeyS" && Ular.dy === 0))
|
||
) {
|
||
ArahUlar = 1;
|
||
Ular.dy = e.code == "KeyW" ? -grid : grid;
|
||
Ular.dx = 0;
|
||
}
|
||
|
||
else if (
|
||
ArahUlar == 0 &&
|
||
((e.code === "ArrowUp" && Ular.dy === 0) ||
|
||
(e.code == "ArrowDown" && Ular.dy === 0))
|
||
) {
|
||
ArahUlar = 1;
|
||
Ular.dy = e.code == "ArrowUp" ? -grid : grid;
|
||
Ular.dx = 0;
|
||
}
|
||
|
||
else if (
|
||
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")
|
||
speed =
|
||
e.code == "KeyE" && speed > 2
|
||
? speed - 1
|
||
: e.code == "KeyQ" && speed < 30
|
||
? speed + 1
|
||
: speed;
|
||
});
|
||
}
|
||
|
||
// nti ae la daud
|
||
// function kirimSkorKeServer(skor, GameMode) {
|
||
// console.log(`Mengirim skor ${skor} (Mode: ${GameMode}) ke server...`);
|
||
|
||
// fetch('score.php', {
|
||
// method: 'POST',
|
||
// headers: {
|
||
// 'Content-Type': 'application/json',
|
||
// },
|
||
// body: JSON.stringify({
|
||
// score: skor,
|
||
// mode: GameMode
|
||
// }),
|
||
// })
|
||
// .then(response => {
|
||
// if (!response.ok) {
|
||
// return response.json().then(error => { throw new Error(error.message || 'Gagal menyimpan skor'); });
|
||
// }
|
||
// return response.json();
|
||
// })
|
||
// .then(data => {
|
||
// if (data.status === 'success') {
|
||
// console.log('✅ Berhasil:', data.message);
|
||
// if (data.message.includes('Highscore baru')) {
|
||
// highscore = skor;
|
||
// UpdateScore(0);
|
||
// }
|
||
// } else {
|
||
// console.error('❌ Error Server:', data.message);
|
||
// }
|
||
// })
|
||
// .catch((error) => {
|
||
// console.error('⚠️ Error Jaringan atau Proses:', error.message);
|
||
// });
|
||
// }
|
||
InputKeyboard();
|
||
gameLoop(); |