diff --git a/GameLogic.js b/GameLogic.js
new file mode 100644
index 0000000..e32a22d
--- /dev/null
+++ b/GameLogic.js
@@ -0,0 +1,271 @@
+ //bagian tempat main ama buat generate game 2d
+ var canvas = document.getElementById("game");
+ var content = canvas.getContext("2d");
+ const Text = document.getElementById("text");
+ const GameoverText = document.getElementById("gameover");
+
+ //settingan awal
+ var grid = 16;
+ var count = 0;
+ var speed = 8;
+ var score = 0;
+ var highscore = 0;
+ var ArahUlar = 0;
+ var GameOverTimer = 0;
+
+ //generate gambar external
+ var KepalaUlarImage = new Image();
+ KepalaUlarImage.src = "image/KepalaHorizontalKanan.png";
+ var KepalAtas = new Image();
+ KepalAtas.src = "image/KepalaVertikalAtas.png";
+ var KepalaBawah = new Image();
+ KepalaBawah.src = "image/KepalaVertikalBawah.png";
+ var KepalaKiri = new Image();
+ KepalaKiri.src = "image/KepalaHorizontalKiri.png";
+ var KepalaKanan = new Image();
+ KepalaKanan.src = "image/KepalaHorizontalKanan.png";
+ // ↑ kepala ular
+
+ var BadanUlarImage = new Image();
+ BadanUlarImage.src = "image/BadanVertikal.png";
+ // ↑ badan ular
+
+ var ApelImage = new Image();
+ ApelImage.src = "image/ApelLayer.png"; // Apel
+ var TembokImage = new Image();
+ TembokImage.src = "image/Tembok.png"; // Tembok Batagor
+
+ //D:\PROYEK UAS\Game ULAR\gambar\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();
+ RandomSpawnWall();
+
+ //mastiin gambar external generate dulu sebelum game start
+ KepalaUlarImage.onload = function () {
+ function gameLoop() {}
+ };
+
+ //gameover terus ngatur ular ke setting awal
+ function gameLoop() {
+ if (GameOverTimer > 0) {
+ GameOverTimer -= 0.006;
+ GameoverText.innerHTML =
+ GameOverTimer > 0
+ ? "Gameover " + GameOverTimer.toFixed(0).toString()
+ : "";
+ if (GameOverTimer <= 0) {
+ Ular.x = 528;
+ Ular.y = 240;
+ Ular.cells = [];
+ Ular.maxCells = 4;
+ Ular.dx = grid;
+ Ular.dy = 0;
+ Tembok = [];
+ RandomizeApel();
+ UpdateScore(0);
+ RandomSpawnWall();
+ }
+ } else {
+ InputKeyboard();
+ ClearCanvas();
+ Movement();
+ IntiGame();
+ }
+ requestAnimationFrame(gameLoop);
+ }
+
+ //random spawn Apel
+ function RandomizeApel() {
+ var pembataslebar = Math.floor(canvas.width / grid);
+ var pembatastinggi = Math.floor(canvas.height / grid);
+ Apel.x = Math.floor(Math.random() * pembataslebar) * grid;
+ Apel.y = Math.floor(Math.random() * pembatastinggi) * grid;
+ }
+
+ 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 (Ular.cells[i].x === TembokX && Ular.cells[i].y === TembokY) {
+ kosong = false;
+ break;
+ }
+ }
+
+ //tidak memperbolehkan tembok spawn sama dengan apel
+ if (TembokX === Apel.x && TembokY === Apel.y) {
+ kosong = false;
+ }
+
+ 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 ... berapa enaknya ya? 😁
+ function PenambahanTembok() {
+ if (Tembok.length < Math.floor(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 +
+ "
Highscore: " +
+ highscore +
+ "
Speed: " +
+ speed;
+
+ PenambahanTembok();
+ }
+
+ //gameover countdown
+ function GameOver() {
+ GameOverTimer = 3;
+ }
+
+ //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);
+ Tembok.forEach(function (bata) {
+ content.drawImage(TembokImage, bata.x, bata.y, grid, grid);
+ });
+
+ Ular.cells.forEach(function (cell, index) {
+ if (index === 0) {
+ // Logika Pemilihan Gambar Kepala Ular
+ var posisiKepalaImage;
+ if (Ular.dx === grid) {
+ // KANAN
+ posisiKepalaImage = KepalaKanan;
+ } else if (Ular.dx === -grid) {
+ // KIRI
+ posisiKepalaImage = KepalaKiri;
+ } else if (Ular.dy === -grid) {
+ // ATAS
+ posisiKepalaImage = KepalAtas;
+ } else if (Ular.dy === grid) {
+ // BAWAH
+ posisiKepalaImage = KepalaBawah;
+ } else {
+ // Default, misalnya saat game baru mulai (dx=grid, dy=0, atau default awal)
+ posisiKepalaImage = KepalaKanan;
+ }
+
+ content.drawImage(posisiKepalaImage, cell.x, cell.y, grid, grid);
+ } else {
+ content.drawImage(BadanUlarImage, cell.x, cell.y, grid, grid);
+ }
+ });
+
+ //bagian generate ular
+ Ular.cells.forEach(function (cell, index) {
+ if (index === 0) {
+ content.drawImage(KepalaUlarImage, cell.x, cell.y, grid, grid);
+ } else {
+ content.drawImage(BadanUlarImage, cell.x, cell.y, grid, grid);
+ }
+
+ //buat pas ular makan Apel
+ if (cell.x === Apel.x && cell.y === Apel.y) {
+ Ular.maxCells += 1;
+ UpdateScore(1);
+ RandomizeApel();
+ }
+
+ //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
+ for (var i = index + 1; i < Ular.cells.length; i++)
+ if (cell.x === Ular.cells[i].x && cell.y === Ular.cells[i].y)
+ GameOver();
+ });
+ }
+
+ 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 buat jalan
+ function InputKeyboard() {
+ document.addEventListener("keydown", function (e) {
+ 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;
+ }
+ if (e.code === "KeyE" || e.code == "KeyQ")
+ speed =
+ e.code == "KeyE" && speed > 4
+ ? speed - 1
+ : e.code == "KeyQ" && speed < 9
+ ? speed + 1
+ : speed;
+ });
+ }
+ gameLoop();
\ No newline at end of file
diff --git a/GameStyle.css b/GameStyle.css
new file mode 100644
index 0000000..80abb67
--- /dev/null
+++ b/GameStyle.css
@@ -0,0 +1,63 @@
+ body {
+ background-color: rgb(24, 24, 24);
+ color: white;
+ text-align: left;
+ font-family: "Comic Sans MS", cursive, sans-serif;
+ font-size: 24px;
+ }
+ header,
+ footer,
+ .HalamanFull {
+ padding-left: 50px;
+ padding-right: 50px;
+ }
+ header,
+ footer {
+ background-color: rgb(18, 18, 18);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+ .HalamanFull {
+ background-color: rgb(28, 28, 28);
+ color: white;
+ height: 100%;
+ display: flex;
+ align-items: left;
+ justify-content: left;
+ padding-bottom: 20px;
+ padding-top: 20px;
+ }
+ .icon {
+ width: 70px;
+ height: 70px;
+ background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Nazi_Swastika.svg/2048px-Nazi_Swastika.svg.png");
+ background-size: cover;
+ margin-right: 20px;
+ margin-left: 20px;
+ }
+ .centered {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ h1 {
+ font-size: 40px;
+ margin-right: 100px;
+ }
+ .text {
+ padding-top: 30px;
+ padding-left: 50px;
+ color: white;
+ }
+ #gameover {
+ color: red;
+ font-size: 90px;
+ position: absolute;
+ top: 280px;
+ left: 300px;
+ }
+ #game {
+ background: rgb(192, 232, 255);
+ border: 1px solid white;
+ }
\ No newline at end of file
diff --git a/game.html b/game.html
index 2e2580c..ba9cf1b 100644
--- a/game.html
+++ b/game.html
@@ -1,74 +1,10 @@
-