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.
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.
Makan titik warna merah sebanyak mungkin untuk mengumpulkan poin. Jangan sampai ular menabrak dinding game.
Tampilan game over.
6. Selesai, menarik sekali bukan?.
Demikian penjelasan dari tutorial ‘Cara Membuat Classic Snake Game dengan JavaScript’. Selamat mencoba.