Cara Membuat Classic Snake Game dengan JavaScript

classic snake game

Berbeda dengan snake game yang lainnya, classic snake game akan menampilkan papan pixel art sebagai tempat bermain game. Dengan menampilkan papan pixel art, maka snake game akan memiki tampilan seperti aplikasi snake game di handphone jadul. Nah, kali ini kita akan mencoba membuat classic snake game tampil di website dengan bantuan dari bahasa pemrograman CSS dan JavaScript.

Bahasa pemrograman CSS digunakan untuk membuat background game, sedangkan bahasa pemrograman JavaScript digunakan menampilkan game dan agar game bisa dimainkan.

Lalu, bagaimana caranya membuat classic snake game dengan bahasa pemrograman CSS dan bahasa pemrograman JavaScript? Mudah kok, yuk langsung saja buka komputer kamu dan ikuti beberapa langkah mudah di bawah ini.

Tutorial

1. Buka XAMPP Control Panel, serta aktifkan Apache.

2. Buka program teks editor yang ter-install di komputer kamu, disini saya menggunakan teks editor Notepad++. Ketikkan kode HTML5 berikut ini.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Membuat Basic Snake Game dengan JavaScript</title>
</head>
<body style="margin: 0; background-color: #b22222">
<div class="game" style="margin: 1rem auto 0; width: 600px">
  <h3 id="score" style="font-family: Arial, Helvetica, sans-serif; color: #ffffff">Tekan tombol panah apa saja untuk mulai bergerak!</h3>
  <h3 id="time" style="font-family: Arial, Helvetica, sans-serif; color: #ffffff">Time: 0.0s</h3>
  <canvas id="snakeGame" width="600" height="600"></canvas>
</div>
</body>
</html>

Simpan kode HTML5 di atas di folder xampplite – htdocs – buat folder baru dengan nama ClassicSnakeGame – simpan kode di atas dengan nama index.html. karena script code CSS hanya sedikit, maka script code CSS langsung ditambahkan di file index.html.

3. Untuk melihat hasil script code di atas, kamu bisa buka browser kamu ketiklah http://localhost/ClassicSnakeGame. Tampilan background classic snake game.

1 11

4. Agar classic snake game bisa dimainkan, ketikkan script code JavaScript berikut di file index.html. letakkan script code JavaScript diantara script <body>…</body>.

<script>
    const arraysMatch = function (arr1, arr2) {
        if (arr1.length !== arr2.length) return false;

        for (let i = 0; i < arr1.length; i++) {
            if (arr1[i] !== arr2[i]) return false;
        }

        return true;
    };

    class SnakeGame {
        constructor(x, y, cs, canvas) {
            // Direction (first arg is x movement, second is y movement: [-1, 0] means 'left', [0, 1] would mean 'down', I hope you get it)
            this.direction = [0, 0];
            // Default states
            this.launched = false;
            this.hasStarted = false;
            // Frames/s
            this.timer = 1e3 / (cs / 2);
            // Running time (for the HTML timer)
            this.runningTime = 0;

            // if there is no context (how would this happen? idk...)
            if (!canvas.getContext('2d')) throw 'nope';

            // Canvas context
            this.ctx = canvas.getContext('2d');

            // Block Size (px)
            this.cs = cs;
            // Amount of blocks in x coordinates
            this.xC = (x - (x % cs)) / cs;
            // Amount of blocks in y coordinates
            this.yC = (y - (y % cs)) / cs;

            // An apple
            this.apple = [Math.floor(Math.random() * this.xC), Math.floor(Math.random() * this.yC)];

            // The snake (nvm the usage of unknown class lmao)
            this.snake = new (class {
                constructor(x0, y0) {
                    this.pos = [[x0, y0], [x0 + 1, y0], [x0 + 2, y0]];
                }
            })((this.xC - (this.xC % 2)) / 2 - 1, (this.yC - (this.yC % 2)) / 2 - 1);
        }

        // The game start method
        async start() {
            // Sey that the game has been started
            this.launched = true;

            // Initialize keys and background
            this.init()

            // Auto-Restart
            while (1) {
                // While the game still runs
                while (this.launched) {
                    // Wait for the next frame
                    await this.wait(this.timer);
                    // Run the frame handler
                    this.run();
                }
            }
        }

        init() {
            // Background rect
            this.ctx.fillStyle = '#222222';
            this.ctx.fillRect(0, 0, 600, 600);

            // Every time a key is down
            addEventListener('keydown', function (e) {
                // The movements (ordered so I can do some maths c:)
                const moves = ['ArrowUp', 'ArrowLeft', 'ArrowDown', 'ArrowRight'];

                // if the key pressed is a valid move key
                if (moves.includes(e.key)) {
                    // The move index
                    const move = moves.indexOf(e.key);

                    if (move % 2 === 0) {
                        // Movement: up or down
                        if (game.direction[0] !== 0 || !game.hasStarted) {
                            // Change the y direction
                            game.direction[1] = move === 0 ? -1 : 1;
                            game.direction[0] = 0;
                            // Set game to started if it is not
                            if (!game.hasStarted) game.hasStarted = true;
                        }
                    } else if (move % 2 === 1) {
                        // Movement: left or right
                        if (game.direction[1] !== 0 || !game.hasStarted) {
                            // Change the x direction
                            game.direction[0] = move === 1 ? -1 : 1;
                            game.direction[1] = 0;
                            // Set game to started if it is not
                            if (!game.hasStarted) game.hasStarted = true;
                        }
                    }
                }
            });
        }

        // Method that run on each frame
        run() {
            if (this.hasStarted) {
                // Move handler
                const positions = this.snake.pos.splice(0, this.snake.pos.length - 1);
                this.snake.pos = [positions[0].map((p, i) => p += this.direction[i]), ...positions];

                if (arraysMatch(this.snake.pos[0], this.apple)) {
                    // Apple Eaten?
                    this.snake.pos.push(this.apple);
                    this.apple = [Math.floor(Math.random() * this.xC), Math.floor(Math.random() * this.yC)];
                } else if (Array.from(this.snake.pos).splice(1, this.snake.pos.length).map(p => arraysMatch(p, this.snake.pos[0])).includes(true)) {
                    // Self hit?
                    alert(`You lose! Your total score was ${this.snake.pos.length - 3}!`);
                    this.hasStarted = false;
                    this.reset();
                }

                if (this.snake.pos[0].map((p, i) => i === 0 ? p < 0 || p > this.xC - 1 : p < 0 || p > this.yC - 1).includes(true)) {
                    // Wall hit?
                    alert(`Kamu kalah! Poin kamu ${this.snake.pos.length - 3}!`);
                    this.hasStarted = false;
                    this.reset();
                }

                // Update game running time
                this.runningTime += this.timer;

                // Change HTML texts
                document.getElementById('score').innerHTML = `Poin kamu ${this.snake.pos.length - 3}.`;
                document.getElementById('time').innerHTML = `Waktu: ${(this.runningTime / 1e3).toFixed(1)}s`;
            }

            // Draw the canvas
            return this.draw();
        }

        draw() {
            // Some constant info
            const { ctx, cs } = this;

            // For each block in the x line
            for (let xC = 0; xC < this.xC; xC++) {
                // For each block in the y line
                for (let yC = 0; yC < this.yC; yC++) {
                    // Location of the block
                    const pos = [xC, yC];
                    // Block draw offset
                    const offset = 3;

                    if (this.snake.pos.map(p => arraysMatch(p, pos)).includes(true)) {
                        // If the current block is a part of the snake
                        if (this.snake.pos.map(p => arraysMatch(p, pos)).indexOf(true) !== 0) ctx.fillStyle = '#41ff41';
                        else ctx.fillStyle = '#ffaa41';
                        ctx.fillRect(xC * cs + offset, yC * cs + offset, cs - 2 * offset, cs - 2 * offset);
                    } else if (arraysMatch(this.apple, pos)) {
                        // If the current block is an apple
                        ctx.fillStyle = '#ff4141';
                        ctx.fillRect(xC * cs + offset, yC * cs + offset, cs - 2 * offset, cs - 2 * offset);
                    } else {
                        // If the current block is nothing special
                        ctx.fillStyle = '#333333';
                        ctx.fillRect(xC * cs + offset, yC * cs + offset, cs - 2 * offset, cs - 2 * offset);
                    }
                }
            }
        }

        // Method to use rather than using intervals, very useful btw
        async wait(t) {
            return new Promise(resolve => setTimeout(() => resolve(), t));
        }

        // Method used to reset the whole game
        reset() {
            this.apple = [Math.floor(Math.random() * this.xC), Math.floor(Math.random() * this.yC)];

            this.snake = new (class {
                constructor(x0, y0) {
                    this.pos = [[x0, y0], [x0 + 1, y0], [x0 + 2, y0]];
                }
            })((this.xC - (this.xC % 2)) / 2 - 1, (this.yC - (this.yC % 2)) / 2 - 1);
          
            // Reset game time
            this.runningTime = 0;
          
            // Set score text
            document.getElementById('score').innerHTML = `You have 0 points.`;
            // Set start text
            document.getElementById('time').innerHTML = `Press any arrow key to start moving!`;
        }
    }

    // Create the game instance
    const game = new SnakeGame(600, 600, 20, document.getElementById('snakeGame'));

    // Start the game
    game.start();
</script>

Jangan lupa untuk Ctrl+S di file index.html.

5. Reload alamat url : http://localhost/ClassicSnakeGame. untuk memulai memainkan classis snake game, tekan tombol panah apa saja di komputer kamu.

2 10

Makan titik warna merah sebanyak mungkin untuk mengumpulkan poin. Jangan sampai ular menabrak dinding game.

3 9

Tampilan game over.

4 7

6. Selesai, menarik sekali bukan?.

Demikian penjelasan dari tutorial ‘Cara Membuat Classic Snake Game dengan JavaScript’. Selamat mencoba.

Komentar

Leave a Reply

Your email address will not be published. Required fields are marked *

Trending Minggu Ini

To Top