Skip to content

Instantly share code, notes, and snippets.

@sigmaray
Last active May 24, 2017 13:17
Show Gist options
  • Save sigmaray/c704b0610f505c970d213d8358a2ec7b to your computer and use it in GitHub Desktop.
Save sigmaray/c704b0610f505c970d213d8358a2ec7b to your computer and use it in GitHub Desktop.
Refactoring popular snake version from jsfiddle.net (https://jsfiddle.net/sethduncan3/6ys5juvt/)
<!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