Snake Game
HTML5 Snake Game
*Featured Code Created by Madhav
Source Code
HTML5 with CSS and JavaScript
<!--
Name : 🐍Snake [ 🎮 Game ]
Author : Madhav Jha
version : 1.3.2
Loader : Snake loader (i.e previously made by the same author)
NOTE : Inform me / Ask permission before using it.
DO NOT COPY , PLEASE !!!
version update : 1.3.2
--new result system added to tell game over or game win
--fullScreen option
--Level system
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0 ">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous" />
<link href="https://fonts.googleapis.com/css?family=Sarabun|Aleo" rel="stylesheet">
<title>🐍Snake [ 🎮 Game ]</title>
<style>
body {
margin:0; padding:0px;
background-color:#262626;
color:white;
font-family: 'Sarabun', sans-serif;
user-select:none;
font-size:14px;
background-image:-webkit-linear-gradient(right,#134E5E,#71B280);
}
#fullScreen,#normScreen {
position:absolute ;
top:10px; right:10px;
width:30px; height:30px;
transition-duration:0.2s;
box-shadow:0 1px 3px rgba(0,0,0,0.12), 0 3px 5px rgba(0,0,0,0.3);
cursor:pointer;
border-radius:50%;
transition-duration:0.3s;
}
#fullScreen:active {
transform:scale(0.8);
box-shadow:none;
}
#normScreen {
transform:scale(0);
}
#normScreen:active {
transform:scale(0.8);
box-shadow:none;
}
.container {
display:block; position:relative ;
margin:auto; width:300px;
margin-left:30px;
margin-top:40px;
filter:blur(3px);
}
#instruction {
position:absolute;
width:84%; height:465px;
max-width:330px;
top:0; bottom:0;left:0; right:0;
margin:auto;
z-index:1;
text-align:center;
background-color:teal;
padding:8px;
transition-duration:.15s;
box-shadow:0 1px 3px rgba(0,0,0,0.12), 0 3px 5px rgba(0,0,0,0.3);
border-radius:8px;
}
h2 {
border:3px dashed white;
padding:12px;
margin:0;
border-radius:8px 8px 0 0;
}
h3 { margin-top:-10px;
margin-bottom:15px; }
img {
width:83%; max-width:430px;
height:255px;
}
#pStart,#playAgain{
width:85%; padding:10px;
max-width:400px;
font-size:20px;
background-image:-webkit-linear-gradient(right,#06beb6,#48b1bf);
color:white;
margin-bottom:5px;
outline:none; border:none;
border-radius:8px;
transition-duration:0.2s;
box-shadow:0 1px 3px rgba(0,0,0,0.12), 0 3px 5px rgba(0,0,0,0.3);
cursor:pointer;
}
#endCard {
position:absolute;
width:85%; height:160px;
max-width:300px;
top:0; bottom:0; left:0; right:0;
margin:auto;
z-index:1;
transform:scale(0);
text-align:center ;
transition-duration:.3s;
}
#result {
position:relative ;
font-size:32px;
z-index:1;
font-weight:bold;
margin:10px;
}
#playAgain {
position:absolute;
width:80%; height:55px;
max-width:270px;
top:0; bottom:0; left:0; right:0;
margin:auto;
z-index:1;
transition-duration:.3s;
}
button:active {
transform:scale(0.83);
box-shadow:none;
}
#canvas {
background-color:#37474F;
box-shadow:0 1px 3px rgba(0,0,0,0.12), 0 3px 5px rgba(0,0,0,0.3);
filter:blur(0);
}
#board {
font-size:24px;
font-family: 'Sarabun', sans-serif;
}
#score {
display:inline-block ;
margin:2px;
}
#playSound {
position:relative;
display:inline-block ;
float:right; margin:5px;
margin-top:-30px;
margin-right:50px;
margin-left:210px;
font-size:24px;
}
#sound,#nosound {
position:absolute ;
cursor:pointer;
}
#sound {
visibility:hidden;
}
footer {
text-align:center;
font-size:10px;
color:#efefef;
font-family: 'Aleo', serif;
}
footer > span {
color:red;
font-size:16px;
}
#food {
display:none;
}
@keyframes pop
{
0%
{ transform:scale(0.7); }
34%
{ transform:scale(1); }
66%
{ transform:scale(0.9); }
100%
{ transform:scale(1); }
}
/* Loader Starts from here */
#container
{ display:block;
position:fixed; top:0;
height:100vh; width:100vw;
background-image:-webkit-linear-gradient(right,#134E5E,#71B280);
visibility:hidden;
animation:vanish 3s linear;
z-index:5;
}
@keyframes vanish {
0%{visibility:visible;}
100%{visibility:hidden;}
}
#container:before {
color:white;
content:"23%";
font-family: 'Aleo', serif;
display:block ;
text-align:center ;
position:relative ;
margin:auto;
top:calc( 50% - 25px);
font-size:22px;
animation:percent 2.97s infinite;
}
@keyframes percent {
0% {content:'0%';}
20% {content:'22%';}
30% {content:'30%';}
40% {content:'43%';}
50% {content:'59%';}
60% {content:'64%';}
70% {content:'71%';}
80% {content:'82%';}
90% {content:'98%';}
100% {content:'100%';}
}
#loader
{
display:block ;
position:relative ;
height:100px; width:100px;
margin:auto;
top:calc( 50% - 100px);
border:10px dashed #93F9B9;
box-shadow:0 0 0 10px rgba(0,0,0,.4), inset 0 0 0 10px rgba(0,0,0,.2);
animation:rotate 8s linear infinite;
}
@keyframes rotate {
100% {transform:rotate(-360deg);}
}
#loader > span
{
display:block ;
position:absolute ;
height:100%; width:100%;
top:0; left:0;
overflow:hidden;
}
#loader > span:before {
content:"";
display:block ;
position:absolute ;
height:100%; width:100%;
top:0; left:0;
border:none;
border-top:10px solid white;
animation:animate 2s linear infinite;
}
@keyframes animate {
0% {left:-100%;}
25% {left:0;}
50%,100% {left:100%;}
}
#loader > span:nth-child(2)
{
transform:rotate(90deg);
}
#loader > span:nth-child(3)
{
transform:rotate(180deg);
}
#loader > span:nth-child(4)
{
transform:rotate(270deg);
}
#loader > span:nth-child(2):before
{
animation-delay:.5s;
}
#loader > span:nth-child(3):before
{
animation-delay:1s;
}
#loader > span:nth-child(4):before
{
animation-delay:1.5s;
}
/* here ends */
</style>
</head>
<body>
<!-- Loader starts -->
<div id="container">
<div id="loader" >
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<!-- Loader ends -->
<div id="instruction" >
<h2>INSTRUCTIONS</h2>
<img id="swipe" src="https://dl.dropbox.com/s/ky6y15fl6rx6zo5/SwipeGesture.png?dl=0"
alt="swipe instruction" />
<h3>Swipe or use arrow keys to control the snake.<br>Click on <i class='fas fa-volume-off'></i> to play music .</h3>
<button id="pStart" onclick="game()">START</button>
</div>
<img id="fullScreen" onclick="openFullscreen()" src='https://dl.dropbox.com/s/mn7r7c9p5hhqil9/full-screen.png?dl=0' alt="icon" />
<img id="normScreen" onclick="closeFullscreen()" src='https://dl.dropbox.com/s/b658owy8dlaf8vr/back.png?dl=0' alt="icon" />
<div id="endCard" >
<i><label id="result"></label></i>
<button id="playAgain" onclick="playAgain()">Play Again</button>
</div>
<div class="container" >
<div id="board">Level : <div id="score">0 - 0</div></div>
<div id="playSound">
<i id='sound' onclick="noPlaySound()" class='fas fa-volume-up'></i>
<i id="nosound" onclick="playSound()" class="fas fa-volume-off"></i>
</div>
<canvas id="canvas"></canvas>
<footer>Made with <span>♥</span> By Madhav <sup> ©</sup>2019 - ∞</footer> </div>
<img id="food" src="https://dl.dropbox.com/s/jka79nx4tj9z7st/food-28x28.png?dl=0" alt="food" />
<!-- To get the clicking sound -->
<audio id="music" autoplay loop>
<source src="https://dl-web.dropbox.com/s/k64a811vpo8f1mz/Snake%20game%20theme%20song%201.mp3?dl=0"
type = "audio/mp3">
</audio>
<audio id="eat" autoplay>
<source src="https://dl-web.dropbox.com/s/kxe1gf2rt232jg2/eat.mp3?dl=0"
type = "audio/mp3">
</audio>
<audio id="scoreM" autoplay>
<source src="https://dl-web.dropbox.com/s/hnt77i48coqa4hw/score%20Sound%20.mp3?dl=0"
type = "audio/mp3">
</audio>
<audio id="lose" autoplay>
<source src="https://dl-web.dropbox.com/s/b618j1vdd4d0fer/dead.mp3?dl=0"
type = "audio/mp3">
</audio>
<script>
//important variables
var canvas,ctx,h,w;
var box = 30,fps = 4;
var foodPic = new Image() ;
var dir = "RIGHT" ;
var music,eat,lose,scoreM;
var count = false ;
var endCard, result, playagain;
var score, level = 0, maxScore = 2 ;
var point = maxScore; var run;
//change in direction on keyboard keypress
document.addEventListener("keydown",direction);
function direction(event) {
var key = event.keyCode;
if(key == 37 && dir != "RIGHT") {
dir = "LEFT";
} else if(key == 38 && dir != "DOWN") {
dir = "UP";
} else if(key == 39 && dir != "LEFT") {
dir = "RIGHT";
}else if(key == 40&&dir!= "UP") {
dir = "DOWN";
}
}
window.onload = function () {
//canvas work
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
w = canvas.width = Math.floor(window.innerWidth/box)*box - 2*box;
h = canvas.height = Math.floor(window.innerHeight/box)*box- 4*box;
//to draw food getting image
var img = document.getElementsByTagName("img")[3];
foodPic.src = img.src;
//the score board
score = document.getElementById("score");
endCard = document.getElementById("endCard");
result = document.getElementById("result");
playagain = document.getElementById("playAgain");
//design,muisc and animation
music = document.getElementById("music");
eat = document.getElementById("eat");
lose = document.getElementById("lose");
scoreM = document.getElementById("scoreM");
//for swiping actions
/* actual swipe capture */
canvas.addEventListener('touchstart', handleTouchStart, false);
canvas.addEventListener('touchmove', handleTouchMove, false);
var xDown = null, yDown = null;
function getTouches(evt) {
return evt.touches ||
evt.originalEvent.touches;
}
function handleTouchStart(evt) {
const firstTouch = getTouches(evt)[0];
xDown = firstTouch.clientX;
yDown = firstTouch.clientY;
}
function handleTouchMove(evt) {
if ( ! xDown || ! yDown )
{ return; }
var xUp = evt.touches[0].clientX;
var yUp = evt.touches[0].clientY;
var xDiff = xDown - xUp;
var yDiff = yDown - yUp;
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
/*Response part*/
if ( xDiff>0&&dir!="RIGHT") {
/* left swipe */
dir = "LEFT";
} else if ( xDiff<0&&dir!="LEFT") {
/* right swipe */
dir = "RIGHT";
}
}
else {
if ( yDiff >0&&dir!="DOWN") {
/* up swipe */
dir = "UP";
} else if ( yDiff <0&&dir!="UP") {
/* down swipe */
dir = "DOWN";
}
}
/* reset values */
xDown = null; yDown = null;
}
/* end */
};
//snake body
var snake = [] ;
snake[0] = {
x:box*3 + box/2,
y:box*3 + box/2,
};
snake[1] = {
x:box*2+ box/2,
y:box*3 + box/2,
};
//new head part
var snakeX = snake[0].x ;
var snakeY = snake[0].y ;
//food location
var food = {
x : box*5,
y : box*5,
};
//function to draw everything
function draw() {
drawGrid();
if(count) {
music.volume = 1;
}
//draw snake
for(var i=0;i<snake.length;i++) {
var color = (i===0)?"teal":"#FFDC3F";
drawArc(snake[i].x,snake[i].y,color);
}
//directions
if(dir=="LEFT") {snakeX -= box ;}
if(dir=="RIGHT") {snakeX += box ;}
if(dir=="UP") {snakeY -= box ;}
if(dir=="DOWN") {snakeY += box ;}
// new head co-ordinates
var newHead = {
x : snakeX ,
y : snakeY,
};
//adding new head
snake.unshift(newHead);
//increment of point if yes we add tail else we dont
if(food.x==snake[0].x - box/2 && food.y==snake[0].y - box/2 ) {
point--;
score.innerText = level + " - " +point ;
if(count) {
eat.volume = 1; eat.play();
}
}else{
snake.pop();
}
//draw food
drawFood();
//check for game over conditions
if(snakeX < 0||snakeX > w||snakeY < 0||snakeY > h||collision(snake)){
clearInterval(run);
result.innerText= 'GAME OVER';
endCard.style.transform="scale(1)";
playagain.style.animation="pop .4s linear";
playagain.innerText = 'PLAY AGAIN';
level =0; maxScore = 2 ;
document.getElementById("canvas").style.filter="blur(1px)";
if(count) {
lose.volume = 1; lose.play();
music.volume = 0;
}
}
//check for game over conditions
if(point === 0 ){
clearInterval(run);
result.innerText= 'YOU WIN';
endCard.style.transform="scale(1)";
playagain.style.animation="pop .4s linear";
playagain.innerText = 'NEXT LEVEL';
document.getElementById("canvas").style.filter="blur(1px)";
if(count) {
scoreM.volume = 1; scoreM.play();
}
level++; maxScore += 5;
}
}
//function to draw grid
function drawGrid() {
//to clear the canvas
ctx.fillStyle = "#37474F";
ctx.fillRect(0, 0, w, h);
for(var i = 0;i<=h/box ;i++) {
//vertical lines
ctx.setLineDash([1, 0.5]);
ctx.beginPath();
ctx.strokeStyle = "#efefef";
ctx.moveTo(0,box*i);
ctx.lineTo(w,box*i);
ctx.stroke();
ctx.closePath();
}
for(var i = 0;i<=w/box ;i++) {
//horizontal lines
ctx.beginPath();
ctx.strokeStyle = "#efefef";
ctx.moveTo(box*i,0);
ctx.lineTo(box*i,h);
ctx.stroke();
}
}
//function to draw snake body
function drawArc(x, y, color){
var r = box/2 - 4;
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x,y,r,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}
//function to draw food
function drawFood () {
var isOkay = true ;
//to check if food is not being printing on the snake
for(var i=1;i<snake.length;i++) {
if(food.x==snake[i].x - box/2 && food.y==snake[i].y - box/2 ) {
isOkay = false ; break;
}
}
//if all fine then draw else change co ordinates
if(isOkay ) {
ctx.drawImage(foodPic,food.x,food.y); } else {
food.x = Math.floor(Math.random()*((w/box)-1))*box;
food.y = Math.floor(Math.random()*((h/box)-1))*box;
drawFood ();
}
}
//to check if snake collides with its body
function collision(array){
for(let i = 1; i < array.length; i++){
if(array[0].x == array[i].x && array[0].y == array[i].y){
return true;
}
}
return false;
}
//to start the game
function game() {
run = setInterval(draw,1000/fps);
document.getElementById("instruction").style.transform="scale(0)";
document.getElementsByClassName("container")[0].style.filter="blur(0)";
}
//to play again
function playAgain() {
dir = "RIGHT" ; point = maxScore ;
score.innerText = level + " - " +point ;
//snake body
snake = [] ;
snake[0] = {
x:box*3 + box/2,
y:box*3 + box/2,
};
snake[1] = {
x:box*2+ box/2,
y:box*3 + box/2,
};
//new head part
snakeX = snake[0].x ;
snakeY = snake[0].y ;
//food location
food = {
x : box*5,
y : box*5,
};
run = setInterval(draw,1000/fps);
result.innerText= '';
endCard.style.transform="scale(0)";
playagain.style.animation="";
document.getElementById("canvas").style.filter="blur(0)";
}
//To control sound
function playSound() {
count = true;
music.play();
eat.play(); eat.volume = 0;
lose.play(); lose.volume = 0;
scoreM.play(); scoreM.volume = 0;
document.getElementById("sound").style.visibility="visible";
document.getElementById("nosound").style.visibility="hidden";
}
function noPlaySound() {
count = false;
music.volume = 0;
eat.volume = 0;
lose.volume = 0;
document.getElementById("sound").style.visibility="hidden";
document.getElementById("nosound").style.visibility="visible";
}
//to get fullScreen
function openFullscreen() {
//variable i.e our full html
let e = document.documentElement;
console.log("FullScreen will only work in your browser not on Sololearn");
document.getElementById("fullScreen").style.transform = 'scale(0)';
document.getElementById("normScreen").style.transform = 'scale(1)';
//checking if fullScreen is approved by user
if (e.requestFullscreen) {
e.requestFullscreen();
} else if (e.mozRequestFullScreen) {
//Firefox
e.mozRequestFullScreen();
} else if (e.webkitRequestFullscreen) {
//Chrome, Safari & Opera
e.webkitRequestFullscreen();
} else if (e.msRequestFullscreen) {
//IE/Edge
e.msRequestFullscreen();
}
}
function closeFullscreen() {
//variable i.e our full html
let e = document.documentElement;
document.getElementById("fullScreen").style.transform = 'scale(1)';
document.getElementById("normScreen").style.transform = 'scale(0)';
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
</script>
</body>
nice
ReplyDelete