The Snake game is a classic and fun project to build using JavaScript. In this guide, we’ll walk through creating a simple Snake game from scratch. We’ll use HTML5 Canvas for rendering and JavaScript for game logic.
What is the Snake Game?
The Snake game involves controlling a snake that moves around the screen. The goal is to eat food to grow longer, while avoiding walls and self-collision. The game ends when the snake hits a wall or itself.
Step 1: Set Up the HTML Structure
First, create an HTML file with a canvas element where the game will be drawn.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<style>
canvas {
border: 2px solid black;
}
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: #f0f0f0;
}
#score {
font-size: 20px;
margin: 10px;
}
</style>
</head>
<body>
<div id="score">Score: 0</div>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script src="snake.js"></script>
</body>
</html>
Step 2: Create the Game Canvas
In the JavaScript file, get the canvas context and set up initial variables.
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
// Game variables
let snake = [
{ x: 200, y: 200 },
{ x: 190, y: 200 },
{ x: 180, y: 200 }
];
let food = { x: 100, y: 100 };
let direction = 'right';
let score = 0;
let gameLoop;
// Grid size
const gridSize = 10;
const tileCount = canvas.width / gridSize;
Step 3: Handle User Input
Listen for keydown events to change the snake’s direction.
document.addEventListener('keydown', changeDirection);
function changeDirection(event) {
const LEFT_KEY = 37;
const RIGHT_KEY = 39;
const UP_KEY = 38;
const DOWN_KEY = 40;
const keyPressed = event.keyCode;
const goingUp = direction === 'up';
const goingDown = direction === 'down';
const goingRight = direction === 'right';
const goingLeft = direction === 'left';
if (keyPressed === LEFT_KEY && !goingRight) {
direction = 'left';
}
if (keyPressed === UP_KEY && !goingDown) {
direction = 'up';
}
if (keyPressed === RIGHT_KEY && !goingLeft) {
direction = 'right';
}
if (keyPressed === DOWN_KEY && !goingUp) {
direction = 'down';
}
}
Step 4: Implement the Game Loop
The game loop updates the game state at regular intervals.
function gameUpdate() {
const head = { x: snake[0].x, y: snake[0].y };
switch(direction) {
case 'up': head.y -= gridSize; break;
case 'down': head.y += gridSize; break;
case 'left': head.x -= gridSize; break;
case 'right': head.x += gridSize; break;
}
// Check for collisions
if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height) {
gameOver();
return;
}
// Check for self-collision
for (let i = 0; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
gameOver();
return;
}
}
snake.unshift(head);
// Check if food is eaten
if (head.x === food.x && head.y === food.y) {
score += 10;
scoreElement.textContent = `Score: ${score}`;
generateFood();
} else {
snake.pop();
}
gameLoop = setTimeout(gameUpdate, 100);
}
Step 5: Draw the Game
The draw function renders the snake and food on the canvas.
function draw() {
// Clear canvas
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw snake
snake.forEach((segment, index) => {
ctx.fillStyle = index === 0 ? 'red' : 'green';
ctx.fillRect(segment.x, segment.y, gridSize - 2, gridSize - 2);
});
// Draw food
ctx.fillStyle = 'blue';
ctx.fillRect(food.x, food.y, gridSize - 2, gridSize - 2);
}
Step 6: Generate Food
Generate new food at random positions.
function generateFood() {
food.x = Math.floor(Math.random() * tileCount) * gridSize;
food.y = Math.floor(Math.random() * tileCount) * gridSize;
}
Step 7: Game Over
Handle game over scenario.
function gameOver() {
clearTimeout(gameLoop);
alert(`Game Over! Score: ${score}`);
// Reset game
snake = [
{ x: 200, y: 200 },
{ x: 190, y: 200 },
{ x: 180, y: 200 }
];
direction = 'right';
score = 0;
scoreElement.textContent = `Score: ${score}`;
generateFood();
gameLoop = setTimeout(gameUpdate, 100);
}
Step 8: Start the Game
Initialize the game by calling the gameUpdate function.
startGame();
function startGame() {
gameLoop = setTimeout(gameUpdate, 100);
}
Frequently Asked Questions
Q: Why does the snake move automatically?
A: The game loop updates the snake’s position at regular intervals, creating the illusion of movement.
Q: How does the snake grow?
A: Every time the snake eats food, a new segment is added to the front of the snake array without removing the last segment.
Q: Why does the game end when the snake hits itself?
A: Self-collision is detected by checking if the snake’s head collides with any part of its body.
Q: How can I make the game faster or slower?
A: Adjust the setTimeout interval in the gameUpdate function.
Conclusion
You’ve now created a fully functional Snake game using JavaScript and HTML5 Canvas. This project demonstrates fundamental concepts like event handling, game loops, and collision detection. Try modifying the code to add features like different levels, power-ups, or a high score system!