Last active
May 24, 2017 13:17
-
-
Save sigmaray/c704b0610f505c970d213d8358a2ec7b to your computer and use it in GitHub Desktop.
Refactoring popular snake version from jsfiddle.net (https://jsfiddle.net/sethduncan3/6ys5juvt/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> | |
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script> | |
<script type="text/javascript"> | |
// Refactoring of snake on https://jsfiddle.net/sethduncan3/6ys5juvt/ | |
// | |
// What was done: | |
// * Adding parameters that can be changed by user | |
// * Give better names to variables and functions | |
// * Get rid of unnecessary variables. Less variables, more understandable code. | |
// * Refactor "keydown". Get rid of magic numbers | |
// | |
// Code is still not perfect. Many things need to be changed. But I think code is better than it was. | |
$(document).ready(function() { | |
//////////////////// | |
// Snake Parameters | |
var CELL_SIZE = 10; | |
var CANVAS_WIDTH = 250; | |
var CANVAS_HEIGHT = 250; | |
var COLOR_2 = 'white'; | |
var COLOR_1 = 'black'; | |
var INTERVAL = 100; // Increasing interval will decrease speed | |
//////////////////// | |
var keys = { | |
37: 'left', | |
38: 'up', | |
39: 'right', | |
40: 'down' | |
}; | |
$canvas = $('<canvas>').attr({ | |
id: 'canvas', | |
width: CANVAS_WIDTH, | |
height: CANVAS_HEIGHT | |
}); | |
$canvas.appendTo('body'); | |
var ctx = $canvas[0].getContext("2d"); | |
// Lets save the cell width in a variable for easy control | |
var direction; | |
var food; | |
var score; | |
// Lets create the snake now | |
var snakeArray; // an array of cells to make up the snake | |
$(document).keydown(function(e) { | |
var key = e.which; | |
// console.log(key); | |
for (keyNumber in keys) { | |
if (keyNumber == key) { | |
e.preventDefault(); | |
if ( | |
!(direction == 'up' && keys[key] == 'down') | |
&& !(direction == 'down' && keys[key] == 'up') | |
&& !(direction == 'left' && keys[key] == 'right') | |
&& !(direction == 'right' && keys[key] == 'left') | |
) { | |
direction = keys[key]; | |
} | |
} | |
} | |
}); | |
function init() { | |
direction = "right"; // default direction | |
createSnake(); | |
createFood(); // Now we can see the food particle | |
// finally lets display the score | |
score = 0; | |
// Lets move the snake now using a timer which will trigger the paint function | |
// every 60ms | |
if (typeof gameLoop != "undefined") clearInterval(gameLoop); | |
gameLoop = setInterval(paint, INTERVAL); | |
} | |
init(); | |
function createSnake() { | |
var length = 3; // Length of the snake | |
snakeArray = []; // Empty array to start with | |
for (var i = length - 1; i >= 0; i--) { | |
// This will create a horizontal snake starting from the top left | |
snakeArray.push({ | |
x: i, | |
y: 0 | |
}); | |
} | |
} | |
// Lets create the food now | |
function createFood() { | |
food = { | |
x: Math.round(Math.random() * (CANVAS_WIDTH - CELL_SIZE) / CELL_SIZE), | |
y: Math.round(Math.random() * (CANVAS_HEIGHT - CELL_SIZE) / CELL_SIZE), | |
}; | |
// This will create a cell with x/y between 0-44 | |
// Because there are 45(450/10) positions accross the rows and columns | |
} | |
// Lets paint the snake now | |
function paint() { | |
// To avoid the snake trail we need to paint the BG on every frame | |
// Lets paint the canvas now | |
ctx.fillStyle = COLOR_1; | |
ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); | |
ctx.strokeStyle = COLOR_2; | |
ctx.strokeRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); | |
// The movement code for the snake to come here. | |
// The logic is simple | |
// Pop out the tail cell and place it infront of the head cell | |
// console.log({'L95 snakeArray[0]': snakeArray[0].y}) | |
var newX = snakeArray[0].x; | |
var newY = snakeArray[0].y; | |
// These were the position of the head cell. | |
// We will increment it to get the new head position | |
// Lets add proper direction based movement now | |
if (direction == "right") newX++; | |
else if (direction == "left") newX--; | |
else if (direction == "up") newY--; | |
else if (direction == "down") newY++; | |
// Lets add the game over clauses now | |
// This will restart the game if the snake hits the wall | |
// Lets add the code for body collision | |
// Now if the head of the snake bumps into its body, the game will restart | |
if (newX == -1 || newX == CANVAS_WIDTH / CELL_SIZE || newY == -1 || newY == CANVAS_HEIGHT / CELL_SIZE || checkCollision(newX, newY, snakeArray)) { | |
// restart game | |
init(); | |
// Lets organize the code a bit now. | |
return; | |
} | |
// Lets write the code to make the snake eat the food | |
// The logic is simple | |
// If the new head position matches with that of the food, | |
// Create a new head instead of moving the tail | |
if (newX == food.x && newY == food.y) { | |
var tail = { | |
x: newX, | |
y: newY | |
}; | |
score++; | |
// Create new food | |
createFood(); | |
} | |
else { | |
var tail = snakeArray.pop(); // pops out the last cell | |
tail.x = newX; | |
tail.y = newY; | |
} | |
// The snake can now eat the food. | |
snakeArray.unshift(tail); // puts back the tail as the first cell | |
for (var i = 0; i < snakeArray.length; i++) { | |
var c = snakeArray[i]; | |
// Lets paint 10px wide cells | |
paintCell(c.x, c.y); | |
} | |
// Lets paint the food | |
paintCell(food.x, food.y); | |
// Lets paint the score | |
var scoreText = "Score: " + score; | |
ctx.fillText(scoreText, 5, CANVAS_HEIGHT - 5); | |
} | |
// Lets first create a generic function to paint cells | |
function paintCell(x, y) { | |
ctx.fillStyle = COLOR_2; | |
ctx.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE); | |
ctx.strokeStyle = COLOR_1; | |
ctx.strokeRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE); | |
} | |
function checkCollision(x, y, array) { | |
// This function will check if the provided x/y coordinates exist | |
// in an array of cells or not | |
for (var i = 0; i < array.length; i++) { | |
if (array[i].x == x && array[i].y == y) return true; | |
} | |
return false; | |
} | |
}); | |
</script> | |
</head> | |
<body> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment