Snake Game using HTML, CSS and JavaScript With Source Code
Introduction :
The Snake Game project is a classic implementation of the iconic Snake arcade game using a combination of HTML, CSS, and JavaScript. This web-based adaptation aims to deliver a nostalgic gaming experience, allowing users to control a snake that grows longer as it consumes randomly placed food items. The project leverages fundamental web technologies to create an interactive and visually engaging game interface. User interaction is facilitated through both keyboard controls and on-screen arrow icons. The player can change the snake’s direction by pressing the arrow keys or by clicking the corresponding arrow icons. This dual-input approach enhances accessibility, catering to users with different preferences.
The HTML file serves as the structural foundation for the Snake Game, defining the layout and key elements. The game board is enclosed within a wrapper, providing a centralized and visually appealing display. Game details, such as the current score and high score, are prominently featured at the top. The play board, where the snake and food elements are dynamically generated, occupies the central portion. Additionally, controls for navigating the snake are represented by arrow icons, enhancing user interaction. The core functionality of the Snake Game is implemented through JavaScript. The game initializes with the snake positioned on the board and the first food item randomly placed. As the game progresses, the snake’s position is updated based on user input or automatic movement. The game dynamically handles collisions, ensuring that the snake grows in length upon consuming food and triggering a game over condition if it collides with the walls or itself. The scoring mechanism is implemented, tracking the player’s score and updating the high score stored in local storage.
Explanation :
HTML Structure:
- The HTML file defines the structure of the Snake Game. It includes a
<div>
wrapper that encompasses the entire game interface, providing a central container for the game elements. - The
<h1>
tag with the “Snake Game” title is centered at the top of the wrapper, acting as a prominent heading for the game. - The game details section (
<div class="game-details">
) includes<span>
elements for displaying the current score and high score. - The actual play board is represented by the
<div class="play-board">
element, where the snake and food elements will be dynamically generated. - The controls section features four arrow icons (
<i>
) corresponding to the arrow keys, providing a visual representation of the controls.
CSS Styling:
- Global styling is applied using the
*
selector to reset margin, padding, and box-sizing properties, ensuring a consistent appearance across different elements. - The overall styling of the game is achieved through a combination of flexbox and grid layout properties. The wrapper employs flex properties to center its contents.
- The game details section (
<div class="game-details">
) has a distinctive color scheme, and the text is styled for clarity and visibility. - The play board (
<div class="play-board">
) utilizes a grid layout to create a 30×30 grid for the snake and food elements. - Specific styles are applied to the food and snake head elements, differentiating them visually from the background and each other.
- The controls section (
<div class="controls">
) is hidden by default but becomes visible on smaller screens, enhancing the game’s responsiveness.
JavaScript Game Logic:
- JavaScript is responsible for implementing the game’s core logic. The script begins by selecting essential elements from the HTML, such as the play board and score displays.
- Variables are declared to store information about the game state, including the snake’s position, velocity, and the current score.
- Functions like
updateFoodPosition
handle the positioning of the food item, andhandleGameOver
manages the game-over scenario. - The
changeDirection
function allows users to control the snake’s movement using keyboard input or on-screen arrow buttons. - The main game loop (
initGame
) updates the snake’s position, checks for collisions, handles scoring, and renders the updated game board. - Local storage is utilized to store and retrieve the player’s high score between game sessions.
User Interaction:
- User interaction is facilitated through keyboard controls (arrow keys) and on-screen arrow icons. The
changeDirection
function captures key presses and adjusts the snake’s velocity accordingly. - On-screen arrow icons are associated with the
data-key
attribute, providing a convenient way to identify the intended direction.
Source Code :
HTML (index.html)
Snake Game JavaScript
Snake Game
Score: 0
High Score: 0
CSS (style.css)
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Open Sans', sans-serif;
}
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: #aaaaaa;
}
.wrapper {
width: 65vmin;
height: 70vmin;
display: flex;
overflow: hidden;
flex-direction: column;
justify-content: center;
border-radius: 5px;
background: #0854d7;
box-shadow: 0 20px 40px rgba(52, 87, 220, 0.2);
}
.game-details {
color: #B8C6DC;
font-weight: 500;
font-size: 1.2rem;
padding: 20px 27px;
display: flex;
justify-content: space-between;
}
.play-board {
height: 100%;
width: 100%;
display: grid;
background: #000000;
grid-template: repeat(30, 1fr) / repeat(30, 1fr);
}
.play-board .food {
background: #37ff00;
}
.play-board .head {
background: #fbff00;
}
.controls {
display: none;
justify-content: space-between;
}
.controls i {
padding: 25px 0;
text-align: center;
font-size: 1.3rem;
color: #B8C6DC;
width: calc(100% / 4);
cursor: pointer;
border-right: 1px solid #171B26;
}
@media screen and (max-width: 800px) {
.wrapper {
width: 90vmin;
height: 115vmin;
}
.game-details {
font-size: 1rem;
padding: 15px 27px;
}
.controls {
display: flex;
}
.controls i {
padding: 15px 0;
font-size: 1rem;
}
}
JavaScript (script.js)
const playBoard = document.querySelector(".play-board");
const scoreElement = document.querySelector(".score");
const highScoreElement = document.querySelector(".high-score");
const controls = document.querySelectorAll(".controls i");
let gameOver = false;
let foodX, foodY;
let snakeX = 5, snakeY = 5;
let velocityX = 0, velocityY = 0;
let snakeBody = [];
let setIntervalId;
let score = 0;
// Getting high score from the local storage
let highScore = localStorage.getItem("high-score") || 0;
highScoreElement.innerText = `High Score: ${highScore}`;
const updateFoodPosition = () => {
// Passing a random 1 - 30 value as food position
foodX = Math.floor(Math.random() * 30) + 1;
foodY = Math.floor(Math.random() * 30) + 1;
}
const handleGameOver = () => {
// Clearing the timer and reloading the page on game over
clearInterval(setIntervalId);
alert("Game Over! Press OK to replay...");
location.reload();
}
const changeDirection = e => {
// Changing velocity value based on key press
if(e.key === "ArrowUp" && velocityY != 1) {
velocityX = 0;
velocityY = -1;
} else if(e.key === "ArrowDown" && velocityY != -1) {
velocityX = 0;
velocityY = 1;
} else if(e.key === "ArrowLeft" && velocityX != 1) {
velocityX = -1;
velocityY = 0;
} else if(e.key === "ArrowRight" && velocityX != -1) {
velocityX = 1;
velocityY = 0;
}
}
// Calling changeDirection on each key click and passing key dataset value as an object
controls.forEach(button => button.addEventListener("click", () => changeDirection({ key: button.dataset.key })));
const initGame = () => {
if(gameOver) return handleGameOver();
let html = ``;
// Checking if the snake hit the food
if(snakeX === foodX && snakeY === foodY) {
updateFoodPosition();
snakeBody.push([foodY, foodX]); // Pushing food position to snake body array
score++; // increment score by 1
highScore = score >= highScore ? score : highScore;
localStorage.setItem("high-score", highScore);
scoreElement.innerText = `Score: ${score}`;
highScoreElement.innerText = `High Score: ${highScore}`;
}
// Updating the snake's head position based on the current velocity
snakeX += velocityX;
snakeY += velocityY;
// Shifting forward the values of the elements in the snake body by one
for (let i = snakeBody.length - 1; i > 0; i--) {
snakeBody[i] = snakeBody[i - 1];
}
snakeBody[0] = [snakeX, snakeY]; // Setting first element of snake body to current snake position
// Checking if the snake's head is out of wall, if so setting gameOver to true
if(snakeX 30 || snakeY 30) {
return gameOver = true;
}
for (let i = 0; i < snakeBody.length; i++) {
// Adding a div for each part of the snake's body
html += ``;
// Checking if the snake head hit the body, if so set gameOver to true
if (i !== 0 && snakeBody[0][1] === snakeBody[i][1] && snakeBody[0][0] === snakeBody[i][0]) {
gameOver = true;
}
}
playBoard.innerHTML = html;
}
updateFoodPosition();
setIntervalId = setInterval(initGame, 100);
document.addEventListener("keyup", changeDirection);
Output :
Find More Projects
Build a Quiz Game Using HTML CSS and JavaScript Introduction Hello coders, you might have played various games, but were you aware …
Emoji Catcher Game Using HTML CSS and JavaScript Introduction Hello Coders, Welcome to another new blog. In this article we’ve made a …
Typing Challenge Using HTML CSS and JavaScript Introduction Hello friends, all you developer friends are welcome to our new project. If you …
Breakout Game Using HTML CSS and JavaScript With Source Code Introduction Hello friends, welcome to today’s new blog post. All of you …
Digital and Analog Clock using HTML CSS and JavaScript Introduction : This project is a digital clock and stopwatch system, which allows …
Coffee Shop Website using HTML, CSS & JavaScript Introduction : This project is a website for coffee house business. It uses HTML …