ScriptCodeSnakeGame
Html:
This will have a basic layout of contents with Canvas Div where we are gonna move snake and Score and level and messages part if Game over:
Java Script:
Here we will have the script code that requires for developing the snake game.
Detailed comments added code snippets:
Pre req: HTMLCanvasElement.getContext() for More info.
Lets Get the canvas from the html and Get 2D element for that canvas.
Script:
// copy and paste in script.js file.
//******** START OF SCRIPT **********
$(function(){
var canvas = $("#canvas")[0];
// Getting the 2D element of canvas.
var ctx = canvas.getContext('2d');
// A Snake with 3 boxes starts at x axis y axis positions one after the other.
var snake = [
{x:50,y:100,oldX:0,oldY:0},
{x:50,y:90,oldX:0,oldY:0},
{x:50,y:80,oldX:0,oldY:0},
];
// initial palce of food element in canvas.
var food = {x: 200,y:200, eaten:false};
// Snake is square with width and eight of 10px.
var snakeWidth = snakeHeight = 10;
var blockSize = 10;
// defining constants for the keyboard keys 4 Arrow keys.
const LEFT = 37;
const UP = 38;
const RIGHT = 39;
const DOWN = 40;
// initially moving towards down
var keyPressed = DOWN;
// score element starts from 0 and increases as game progress
var score = 0;
var game;
var speed = 300;
// calling this method based on the interval speeds.
startInterval(speed);
// for every micro seconds this method will be invoked
function startInterval(speed){
game = setInterval(gameLoop, speed);
}
// This is the crucial method which will be called on every microsecond speed element
function gameLoop(){
console.log("drawing");
clearCanvas(); // to clear existing position of snake
drawFood(); // to draw a new food in canvas
moveSnake(); // to move snake based on keys pressed
drawSnake(); // to draw a new snake in that directions
}
// Based on the key pressed we will be moving all the blocks one by one to its new positions.
// all we need to take care is head and tail in snake.
// we Move head first and all other blocks shifts its positions to previous block positions.
function moveSnake(){
$.each(snake,function(index,value){
snake[index].oldX = value.x;
snake[index].oldY = value.y;
if(index == 0){
if(keyPressed == DOWN){
snake[index].y = value.y + blockSize;
} else if(keyPressed == UP){
snake[index].y = value.y - blockSize;
}else if(keyPressed == RIGHT){
snake[index].x = value.x + blockSize;
}else if(keyPressed == LEFT){
snake[index].x = value.x - blockSize;
}
}else{
snake[index].x = snake[index - 1].oldX;
snake[index].y = snake[index -1].oldY;
}
})
}
// To make snake visible we need to draw on canvas
//we use fillStyle for color, fillRect which accepts 4 params x position, y position, width and height
// by the below method that blocks are drawn.
function drawSnake(){
$.each(snake,function(index,value){
ctx.fillStyle = 'red';
ctx.fillRect(value.x,value.y,snakeWidth,snakeHeight);
ctx.strokeStyle = 'black';
ctx.strokeRect(value.x,value.y,snakeWidth,snakeHeight);
if(index == 0){ // we will do only for head
if(collided(value.x,value.y)){ // validating of body collided to itself or any walls
gameOver();
}
if(didEatFood(value.x,value.y)){ // Feed the snake
score +=10;
$("#score").text(score);
increaseSnake(); // Increate snake size by 1 block
food.eaten = true;
// to define speed and levels Starts here
if(score > 500){
$("#level").text("TOP Level");
speed = 300;
clearInterval(game);
startInterval(speed);
}else if(score > 300){
$("#level").text("5");
speed = 200;
clearInterval(game);
startInterval(speed);
}else if(score > 200){
$("#level").text("4");
speed = 100;
clearInterval(game);
startInterval(speed);
}else if(score > 100){
$("#level").text("3");
speed = 50;
clearInterval(game);
startInterval(speed);
}else if(score > 50){
$("#level").text("2");
speed = 100;
clearInterval(game);
startInterval(speed);
}
}
}
});
}
// Collision check for validating game over or not
// Check like any body positions is same or touching the canvas start or end positions in all 4 sides
function collided(x,y){
return snake.filter(function(value,index){
return index != 0 && value.x == x && value.y == y;
}).length > 0 || x < 0 || x > canvas.width || y < 0 || y > canvas.height ;
}
// Increase the size of the snake by adding one block exactly at the end of the last block
function increaseSnake(){
snake.push({
x:snake[snake.length-1].oldX,
y:snake[snake.length-1].oldY
});
}
// check snake touched the food position and if touched make it return as eaten.
function didEatFood(x,y) {
return food.x == x && food.y == y;
}
// Draw a food in yellow box and condition here is
// -> it should not be outside the canvas
// -> it should not be in potions of Snake body
function drawFood(){
ctx.fillStyle = 'yellow';
if(food.eaten == true){
food = getNewPositionForFood();
}
ctx.fillRect(food.x,food.y,snakeWidth,snakeHeight);
}
// create canvas
function clearCanvas(){
ctx.clearRect(0,0,canvas.width,canvas.height);
}
// validate and block other key events of keyboard
$(document).keydown(function(evt){
if($.inArray(evt.which,[DOWN,UP,LEFT,RIGHT]) != -1){
keyPressed = checkIsThisKeyAllowed(evt.which);
}
});
// Allow only 4 arrow keys
function checkIsThisKeyAllowed(tempKey){
let key;
if(tempKey == DOWN){
key = (keyPressed != UP) ? tempKey : keyPressed;
}else if(tempKey == UP){
key = (keyPressed != DOWN) ? tempKey : keyPressed;
}else if(tempKey == RIGHT){
key = (keyPressed != LEFT) ? tempKey : keyPressed;
}else if(tempKey == LEFT){
key = (keyPressed != RIGHT) ? tempKey : keyPressed;
}
return key;
}
// code if game is over
function gameOver(){
clearInterval(game);
$("#gameUp").text("GAME OVER");
$("#gameUp").show();
}
// How to get the new position of food:
// As i said earlier we should get a random position and that position should be within canvas
// That position should not be in the snake body.
function getNewPositionForFood(){
let xArr = yArr = [],xy;
$.each(snake,function(index,value){
if($.inArray(value.x, xArr) != -1 ){
xArr.push(value.x);
}
if($.inArray(value.y,yArr) == -1){
yArr.push(value.y);
}
});
xy = getEmptyXY(xArr,yArr);
return xy;
}
// Get the empty location in canvas
function getEmptyXY(xArr,yArr){
let newX,newY;
newX = getRandomNumber(canvas.width - 10,10);
newY = getRandomNumber(canvas.height - 10,10);
if($.inArray(newX, xArr) == -1 && $.inArray(newY,yArr) != -1){
return {
x:newX,
y:newY,
eaten:false
}
}else{
return getEmptyXY(xArr,yArr);
}
}
// logic to get random number.
function getRandomNumber(max,multipleOf){
let result = Math.floor(Math.random() * max);
result = (result % 10 == 0) ? result : result + (multipleOf - result % 10);
return result;
}
});
//***** END OF SCRIPT **********
Details of the Html and Script code for Snake Game:
You Can clone or download from my Here JavaScriptSnakeGameHtml:
This will have a basic layout of contents with Canvas Div where we are gonna move snake and Score and level and messages part if Game over:
<!DOCTYPE html>
<html>
<head>
<title>snake game</title>
<style type="text/css">
#container{
text-align: center;
}
#canvas{
background-color: black;
}
</style>
</head>
<body>
<div id="container">
<canvas id="canvas" width="600" height="400">
</canvas>
<span>Score:<b id="score">0</b></span><span> Level:<b id="level">0</b></span>
<div id="gameUp" style="font-size: 80px;color:red;display:none">
</div>
<ul style="text-align: left">
<li style="color: red">Touch The walls Game Over</li>
<li>Score 50+ to reach Level 2 ** Speed increases</li>
<li>Score 100+ to reach Level 3 ** <b style="color: red">Speed increases</b></li>
<li>Score 200+ to reach Level 4 ** Speed decreases</li>
<li>Score 300+ to reach Level 5 ** Speed increases</li>
<li>Score 500+ to reach <b style="color: green">****Top Level*****</b></li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="script.js"> </script>
</body>
</html>
Java Script:
Here we will have the script code that requires for developing the snake game.
Detailed comments added code snippets:
- Draw the Snake
- Move the Snake
- Feed the Snake
- Create the Food for Snake
- Validate if touches walls.
Pre req: HTMLCanvasElement.getContext() for More info.
Lets Get the canvas from the html and Get 2D element for that canvas.
Script:
// copy and paste in script.js file.
//******** START OF SCRIPT **********
$(function(){
var canvas = $("#canvas")[0];
// Getting the 2D element of canvas.
var ctx = canvas.getContext('2d');
// A Snake with 3 boxes starts at x axis y axis positions one after the other.
var snake = [
{x:50,y:100,oldX:0,oldY:0},
{x:50,y:90,oldX:0,oldY:0},
{x:50,y:80,oldX:0,oldY:0},
];
// initial palce of food element in canvas.
var food = {x: 200,y:200, eaten:false};
// Snake is square with width and eight of 10px.
var snakeWidth = snakeHeight = 10;
var blockSize = 10;
// defining constants for the keyboard keys 4 Arrow keys.
const LEFT = 37;
const UP = 38;
const RIGHT = 39;
const DOWN = 40;
// initially moving towards down
var keyPressed = DOWN;
// score element starts from 0 and increases as game progress
var score = 0;
var game;
var speed = 300;
// calling this method based on the interval speeds.
startInterval(speed);
// for every micro seconds this method will be invoked
function startInterval(speed){
game = setInterval(gameLoop, speed);
}
// This is the crucial method which will be called on every microsecond speed element
function gameLoop(){
console.log("drawing");
clearCanvas(); // to clear existing position of snake
drawFood(); // to draw a new food in canvas
moveSnake(); // to move snake based on keys pressed
drawSnake(); // to draw a new snake in that directions
}
// Based on the key pressed we will be moving all the blocks one by one to its new positions.
// all we need to take care is head and tail in snake.
// we Move head first and all other blocks shifts its positions to previous block positions.
function moveSnake(){
$.each(snake,function(index,value){
snake[index].oldX = value.x;
snake[index].oldY = value.y;
if(index == 0){
if(keyPressed == DOWN){
snake[index].y = value.y + blockSize;
} else if(keyPressed == UP){
snake[index].y = value.y - blockSize;
}else if(keyPressed == RIGHT){
snake[index].x = value.x + blockSize;
}else if(keyPressed == LEFT){
snake[index].x = value.x - blockSize;
}
}else{
snake[index].x = snake[index - 1].oldX;
snake[index].y = snake[index -1].oldY;
}
})
}
// To make snake visible we need to draw on canvas
//we use fillStyle for color, fillRect which accepts 4 params x position, y position, width and height
// by the below method that blocks are drawn.
function drawSnake(){
$.each(snake,function(index,value){
ctx.fillStyle = 'red';
ctx.fillRect(value.x,value.y,snakeWidth,snakeHeight);
ctx.strokeStyle = 'black';
ctx.strokeRect(value.x,value.y,snakeWidth,snakeHeight);
if(index == 0){ // we will do only for head
if(collided(value.x,value.y)){ // validating of body collided to itself or any walls
gameOver();
}
if(didEatFood(value.x,value.y)){ // Feed the snake
score +=10;
$("#score").text(score);
increaseSnake(); // Increate snake size by 1 block
food.eaten = true;
// to define speed and levels Starts here
if(score > 500){
$("#level").text("TOP Level");
speed = 300;
clearInterval(game);
startInterval(speed);
}else if(score > 300){
$("#level").text("5");
speed = 200;
clearInterval(game);
startInterval(speed);
}else if(score > 200){
$("#level").text("4");
speed = 100;
clearInterval(game);
startInterval(speed);
}else if(score > 100){
$("#level").text("3");
speed = 50;
clearInterval(game);
startInterval(speed);
}else if(score > 50){
$("#level").text("2");
speed = 100;
clearInterval(game);
startInterval(speed);
}
}
}
});
}
// Collision check for validating game over or not
// Check like any body positions is same or touching the canvas start or end positions in all 4 sides
function collided(x,y){
return snake.filter(function(value,index){
return index != 0 && value.x == x && value.y == y;
}).length > 0 || x < 0 || x > canvas.width || y < 0 || y > canvas.height ;
}
// Increase the size of the snake by adding one block exactly at the end of the last block
function increaseSnake(){
snake.push({
x:snake[snake.length-1].oldX,
y:snake[snake.length-1].oldY
});
}
// check snake touched the food position and if touched make it return as eaten.
function didEatFood(x,y) {
return food.x == x && food.y == y;
}
// Draw a food in yellow box and condition here is
// -> it should not be outside the canvas
// -> it should not be in potions of Snake body
function drawFood(){
ctx.fillStyle = 'yellow';
if(food.eaten == true){
food = getNewPositionForFood();
}
ctx.fillRect(food.x,food.y,snakeWidth,snakeHeight);
}
// create canvas
function clearCanvas(){
ctx.clearRect(0,0,canvas.width,canvas.height);
}
// validate and block other key events of keyboard
$(document).keydown(function(evt){
if($.inArray(evt.which,[DOWN,UP,LEFT,RIGHT]) != -1){
keyPressed = checkIsThisKeyAllowed(evt.which);
}
});
// Allow only 4 arrow keys
function checkIsThisKeyAllowed(tempKey){
let key;
if(tempKey == DOWN){
key = (keyPressed != UP) ? tempKey : keyPressed;
}else if(tempKey == UP){
key = (keyPressed != DOWN) ? tempKey : keyPressed;
}else if(tempKey == RIGHT){
key = (keyPressed != LEFT) ? tempKey : keyPressed;
}else if(tempKey == LEFT){
key = (keyPressed != RIGHT) ? tempKey : keyPressed;
}
return key;
}
// code if game is over
function gameOver(){
clearInterval(game);
$("#gameUp").text("GAME OVER");
$("#gameUp").show();
}
// How to get the new position of food:
// As i said earlier we should get a random position and that position should be within canvas
// That position should not be in the snake body.
function getNewPositionForFood(){
let xArr = yArr = [],xy;
$.each(snake,function(index,value){
if($.inArray(value.x, xArr) != -1 ){
xArr.push(value.x);
}
if($.inArray(value.y,yArr) == -1){
yArr.push(value.y);
}
});
xy = getEmptyXY(xArr,yArr);
return xy;
}
// Get the empty location in canvas
function getEmptyXY(xArr,yArr){
let newX,newY;
newX = getRandomNumber(canvas.width - 10,10);
newY = getRandomNumber(canvas.height - 10,10);
if($.inArray(newX, xArr) == -1 && $.inArray(newY,yArr) != -1){
return {
x:newX,
y:newY,
eaten:false
}
}else{
return getEmptyXY(xArr,yArr);
}
}
// logic to get random number.
function getRandomNumber(max,multipleOf){
let result = Math.floor(Math.random() * max);
result = (result % 10 == 0) ? result : result + (multipleOf - result % 10);
return result;
}
});
//***** END OF SCRIPT **********
No comments:
Post a Comment