2025-12-13 21:37:33 +07:00

480 lines
15 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// //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;
    highscore = score > highscore ? score : highscore;
   
    Text.innerHTML =
        "Score: " + score + "<br>Highscore: " + highscore + "<br>Speed: " + speed;
    PenambahanTembok();
}
//tampilin gameover
function GameOver() {
    GameStart = false;
    ClearCanvas();
    const GameMode = ModeH ? "Tambahan" : "Normal";
    if (score > 0) {
    }
    ScoreMain.innerHTML = "Score: " + score;
    UpDead.style.display = "flex";
}
//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;
            }
        }
// Belokan (Dibalik: Atas menggunakan kondisi Bawah, Bawah menggunakan kondisi Atas)
    else {
// belok.AtasKanan (Menggunakan logika BawahKanan sebelumnya)
            if ((ArahMasuk === "bawah" && ArahKeluar === "kanan") || (ArahMasuk === "kiri" && ArahKeluar === "atas"))
gambarUlar = belok.AtasKanan;
           
// belok.AtasKiri (Menggunakan logika BawahKiri sebelumnya)
else if ((ArahMasuk === "bawah" && ArahKeluar === "kiri") || (ArahMasuk === "kanan" && ArahKeluar === "atas"))
gambarUlar = belok.AtasKiri;
            // belok.BawahKanan (Menggunakan logika AtasKanan sebelumnya)
else if ((ArahMasuk === "atas" && ArahKeluar === "kanan") || (ArahMasuk === "kiri" && ArahKeluar === "bawah"))
gambarUlar = belok.BawahKanan;
            // belok.BawahKiri (Menggunakan logika AtasKiri sebelumnya)
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();