Step-by-Step Guide to Creating a Fun and Addictive Snake Game Using Web Technologies.
Learn the Basics of HTML, CSS, and JavaScript While Creating a Fun Game.
Building a complete Snake game in HTML, CSS, and JavaScript is an exciting and rewarding experience for anyone interested in web development and game design. In this tutorial, we will walk you through the process of building a fully functional Snake game from scratch.
Before we begin, it's essential to have a basic understanding of HTML, CSS, and JavaScript. We will be using HTML to create the game board, CSS to style the game elements, and JavaScript to handle the game logic and functionality.
Step 1: Setting up the HTML structure
The first step in creating our Snake game is to create the HTML structure for the game board. We will use the HTML5 canvas element to draw the game board and the game elements on it. Here's an example of the HTML code for our game board:
<!DOCTYPE html>
<html>
<head>
<title>Snake Game</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<canvas id="gameBoard"></canvas>
<script src="script.js"></script>
</body>
</html>
In this code, we create a canvas element with an id of "gameBoard" and link our CSS and JavaScript files.
Step 2: Styling the game board
Now that we have our HTML structure, let's add some styles to make our game board look more visually appealing. We will create a new file called "styles.css" and add the following styles to it:
body {
background-color: #1d2021;
}
canvas {
display: block;
margin: auto;
border: 2px solid #fff;
}
In this code, we set the background color of the body to a dark grayish color and set the canvas to display as a block and centered using the margin property. We also add a white border around the canvas to give it a visual separation from the background.
Step 3: Drawing the snake and food
Now that we have our HTML structure and styles, let's move on to the game logic. The first thing we need to do is draw the snake and food on the game board. We will create a new file called "script.js" and add the following code to it:
const canvas = document.getElementById("gameBoard");
const ctx = canvas.getContext("2d");
const cellSize = 10;
const gameBoardWidth = canvas.width / cellSize;
const gameBoardHeight = canvas.height / cellSize;
let snake = [
{ x: 5, y: 5 },
{ x: 4, y: 5 },
{ x: 3, y: 5 },
];
let food = {
x: Math.floor(Math.random() * gameBoardWidth),
y: Math.floor(Math.random() * gameBoardHeight),
};
function drawSnake() {
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
snake.forEach((segment) => {
ctx.fillRect(segment.x * cellSize, segment.y * cellSize, cellSize, cellSize);
ctx.strokeRect(segment.x * cellSize, segment.y * cellSize, cellSize, cellSize);
});
}
function drawFood() {
ctx.fillStyle = "red";
ctx.fillRect(food.x * cellSize, food.y * cellSize, cellSize, cellSize);
}
drawSnake();
drawFood();
In this code, we create a canvas and context object, define the cell size of the game elements, and the width and height of the game board. We also create an array to store the initial positions of the snake and randomly generate the position of the food on the game board.
function drawSnake() { ctx.fillStyle = "white"; ctx.strokeStyle = "black"; snake.forEach((segment) => { ctx.fillRect(segment.x cellSize, segment.y cellSize, cellSize, cellSize); ctx.strokeRect(segment.x cellSize, segment.y cellSize, cellSize, cellSize); }); }
function drawFood() { ctx.fillStyle = "red"; ctx.fillRect(food.x cellSize, food.y cellSize, cellSize, cellSize); }
drawSnake(); drawFood();
The drawSnake() function fills each segment of the snake with a white color and adds a black border around it. The drawFood() function fills the food position on the game board with a red color.
Step 4: Moving the snake
Now, let's add the functionality to move the snake using the arrow keys. We will create an event listener to listen for key presses and update the snake's position accordingly. Add the following code to the script.js file:
let dx = 1;
let dy = 0;
document.addEventListener("keydown", (e) => {
if (e.code === "ArrowUp" && dy !== 1) {
dx = 0;
dy = -1;
}
if (e.code === "ArrowDown" && dy !== -1) {
dx = 0;
dy = 1;
}
if (e.code === "ArrowLeft" && dx !== 1) {
dx = -1;
dy = 0;
}
if (e.code === "ArrowRight" && dx !== -1) {
dx = 1;
dy = 0;
}
});
In this code, we initialize variables for the direction of the snake and add an event listener to the document to listen for key presses. If the arrow keys are pressed and the snake is not moving in the opposite direction, we update the direction of the snake accordingly.
Step 5: Updating the snake's position
Now that we can move the snake, we need to update its position on the game board. We will create a new function called updateSnake() that will handle the snake's movement and collision detection. Add the following code to the script.js file:
function updateSnake() {
const head = { x: snake[0].x + dx, y: snake[0].y + dy };
snake.unshift(head);
if (head.x === food.x && head.y === food.y) {
food = {
x: Math.floor(Math.random() * gameBoardWidth),
y: Math.floor(Math.random() * gameBoardHeight),
};
} else {
snake.pop();
}
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updateSnake();
drawSnake();
drawFood();
requestAnimationFrame(gameLoop);
}
gameLoop();
In this code, we create a function called updateSnake() that adds a new head to the snake's position based on the direction of movement. If the snake's head position matches the food position, we randomly generate a new position for the food. Otherwise, we remove the last segment of the snake to simulate movement. We also create a gameLoop() function that clears the canvas, updates the snake's position, draws the snake and food on the game board, and requests an animation frame for the next loop.
Step 6: Updating the snake's position and handling collisions
To update the snake's position, we need to create a new function called updateSnake(). This function will be responsible for adding a new head to the snake's array, removing the tail of the snake (if the snake hasn't eaten food), and generating new food when the snake collides with it.
Here's the code for the updateSnake() function:
function updateSnake() {
// Create a new head for the snake
const head = { x: snake[0].x + dx, y: snake[0].y + dy };
snake.unshift(head); // Add the new head to the beginning of the array
// Check if the snake has collided with food
if (head.x === food.x && head.y === food.y) {
// Generate a new position for the food
food = {
x: Math.floor(Math.random() * gameBoardWidth),
y: Math.floor(Math.random() * gameBoardHeight),
};
} else {
// Remove the tail of the snake
snake.pop();
}
}
In this code, we create a new head for the snake by adding the current direction to the coordinates of the first element in the snake array. We then add the new head to the beginning of the array using the unshift() method.
Next, we check if the new head of the snake has collided with the food. If it has, we generate a new position for the food using the Math.random() method and assign it to the food variable. If the snake hasn't collided with food, we remove the last element in the array using the pop() method to simulate the snake's movement.
We also need to modify the gameLoop() function to call the updateSnake() function and check for collisions using the checkCollision() function. Here's the updated gameLoop() function:
function gameLoop() {
// Clear the canvas on each frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Update the snake's position and draw it on the canvas
updateSnake();
drawSnake();
// Draw the food on the canvas
drawFood();
// Check for collisions
if (checkCollision()) {
alert("Game Over!");
// Reset the snake's position and generate new food
snake = [{ x: 10, y: 10 }];
dx = 1;
dy = 0;
food = {
x: Math.floor(Math.random() * gameBoardWidth),
y: Math.floor(Math.random() * gameBoardHeight),
};
}
// Call the gameLoop() function recursively to create an animation loop
requestAnimationFrame(gameLoop);
}
In this code, we first clear the canvas using the clearRect() method. We then call the updateSnake() function to update the snake's position and draw it on the canvas using the drawSnake() function.
Next, we draw the food on the canvas using the drawFood() function.
We then check for collisions using the checkCollision() function. If a collision is detected, we display an alert message to the user, reset the snake's position and direction, and generate new food using the Math.random() method.
Finally, we call the gameLoop() function recursively using the requestAnimationFrame() method to create an animation loop for the game.
Step 7: Styling the game
To make the game look more visually appealing, we can add some styling to the HTML and CSS files. Here's some example CSS code to get you started:
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #222;
}
canvas {
border: 2px solid #fff;
background-color: #333;
}
In this code, we set the background color of the body element to a dark gray and center the canvas on the page. We also give the canvas a white border and a slightly lighter background color.
And there you have it! You now have a complete snake game built with HTML, CSS, and JavaScript. Of course, there are many ways to improve and customize this game, such as adding a score tracker, changing the colors and fonts, and implementing different game modes or difficulty levels. But this should give you a solid foundation to build upon and have some fun with. Happy coding!