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>&#9829;</span> By Madhav <sup> &copy</sup>2019 - &infin;</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>

Click here to Play and be Inspired by 600+ Free HTML5 Games




Comments

Post a Comment

Popular posts from this blog

Multi-tap Keypad Text Entry

Crypto Mining