Creating a Simple Snake Game Using JavaScript

The classic Snake game is a fun and interactive way to practice your JavaScript skills. In this tutorial, we’ll build a simple Snake game using HTML, CSS, and JavaScript.

Overview

We’ll create a game where the player controls a snake that moves around the game board, eats food, and grows longer. The game ends if the snake collides with itself.

JavaScript Logic

Create a script.js file and add the following code:

const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
const grid = 20;
let count = 0;

// Snake object
let snake = {
x: 160,
y: 160,
dx: grid, // Horizontal movement
dy: 0, // Vertical movement
cells: [], // Array of cells occupied by the snake
maxCells: 4 // Initial length of the snake
};

// Apple object
let apple = {
x: 320,
y: 320
};

// Generate a random position for the apple
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) * grid;
}

// Game loop function
function loop() {
requestAnimationFrame(loop);

// Slow down the game loop to control the speed
if (++count < 4) {
return;
}
count = 0;

// Clear the canvas
context.clearRect(0, 0, canvas.width, canvas.height);

// Move the snake
snake.x += snake.dx;
snake.y += snake.dy;

// Wrap the snake position on the edges (uncomment to enable wall-less mode)
// if (snake.x < 0) { // snake.x = canvas.width - grid; // } else if (snake.x >= canvas.width) {
// snake.x = 0;
// }

// if (snake.y < 0) { // snake.y = canvas.height - grid; // } else if (snake.y >= canvas.height) {
// snake.y = 0;
// }

// End the game if the snake hits the wall
if (snake.x < 0 || snake.x >= canvas.width || snake.y < 0 || snake.y >= canvas.height) {
resetGame();
}

// Add the new head position to the beginning of the cells array
snake.cells.unshift({ x: snake.x, y: snake.y });

// Remove cells as the snake moves away
if (snake.cells.length > snake.maxCells) {
snake.cells.pop();
}

// Draw the apple
context.fillStyle = 'red';
context.fillRect(apple.x, apple.y, grid - 1, grid - 1);

// Draw the snake
context.fillStyle = 'lime';
snake.cells.forEach(function (cell, index) {
context.fillRect(cell.x, cell.y, grid - 1, grid - 1);

// Check if the snake ate the apple
if (cell.x === apple.x && cell.y === apple.y) {
snake.maxCells++;

// Generate a new apple position
apple.x = getRandomInt(0, canvas.width / grid);
apple.y = getRandomInt(0, canvas.height / grid);
}

// Check for collision with the snake itself
for (let i = index + 1; i < snake.cells.length; i++) {
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
resetGame();
}
}
});
}

// Reset the game to the initial state
function resetGame() {
snake.x = 160;
snake.y = 160;
snake.dx = grid;
snake.dy = 0;
snake.cells = [];
snake.maxCells = 4;
apple.x = getRandomInt(0, canvas.width / grid);
apple.y = getRandomInt(0, canvas.height / grid);
}

// Keyboard event listeners to control the snake
document.addEventListener('keydown', function (e) {
// Prevent the snake from reversing
if (e.key === 'ArrowLeft' && snake.dx === 0) {
snake.dx = -grid;
snake.dy = 0;
} else if (e.key === 'ArrowUp' && snake.dy === 0) {
snake.dy = -grid;
snake.dx = 0;
} else if (e.key === 'ArrowRight' && snake.dx === 0) {
snake.dx = grid;
snake.dy = 0;
} else if (e.key === 'ArrowDown' && snake.dy === 0) {
snake.dy = grid;
snake.dx = 0;
}
});

// Start the game
requestAnimationFrame(loop);

Explanation

Variables:

  • canvas and context are used to draw on the canvas element.
  • grid defines the size of each cell in the game grid.
  • count is used to control the game speed.
  • snake object holds the snake’s position, direction, body cells, and length.
  • apple object holds the apple’s position.

getRandomInt Function:

  • Generates a random integer within a specified range, multiplied by grid to align with the grid.

Game Loop (loop Function):

  • Uses requestAnimationFrame for smooth animation.
  • Controls the game speed by skipping frames.
  • Clears the canvas each frame.
  • Updates the snake’s position.
  • Checks for collisions with walls.
  • Adds the new head position to the snake’s body.
  • Removes the tail cell if the snake hasn’t grown.
  • Draws the apple and the snake.
  • Checks for collisions with the apple and the snake’s own body.

resetGame Function:

  • Resets the snake and apple to their initial positions and sizes.

Keyboard Controls:

  • Listens for arrow key presses to change the snake’s direction.
  • Prevents the snake from moving in the opposite direction instantly.

Running the Game

To run the game:

  1. Save the index.html and script.js files in the same directory.
  2. Open index.html in a web browser that supports the HTML5 canvas (most modern browsers do).
  3. Use the arrow keys to control the snake and try to eat as many apples as possible without colliding with the walls or yourself.

Enhancements

Here are some ideas to improve the game:

  • Score Tracking: Display the player’s score based on how many apples they’ve eaten.
  • Levels and Speed Increase: Increase the game’s speed as the player eats more apples.
  • Sound Effects: Add sounds for eating apples and game over events.
  • Graphics: Replace the simple squares with images or more intricate graphics.
  • High Scores: Implement a high score table using local storage.

Leave a Reply

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