Created
September 16, 2014 18:00
-
-
Save 1995eaton/469f5d5aad9163e6b2d5 to your computer and use it in GitHub Desktop.
Classic snake game in JavaScript + HTML5 Canvas
This file contains 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 lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title></title> | |
<meta name="description" content=""> | |
<meta name="author" content=""> | |
<style> | |
#canvas { | |
border: 1px solid; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="canvas"></canvas> | |
</body> | |
<script> | |
var WIDTH = 70; | |
var HEIGHT = 70; | |
var SIZE = 10; | |
var LEFT = 37, | |
RIGHT = 39, | |
UP = 38, | |
DOWN = 40; | |
var Grid = function(width, height) { | |
this.width = width; | |
this.height = height; | |
this.data = Array.apply(null, new Array(height)) | |
.map(function() { return new Uint8Array(width); }); | |
}; | |
Grid.prototype = { | |
set: function(x, y, v) { | |
if (this.data[y]) { | |
this.data[y][x] = v; | |
} | |
}, | |
at: function(x, y) { | |
if (this.data[y] === void 0 || this.data[y][x] === void 0) { | |
return 1; | |
} | |
return this.data[y][x]; | |
} | |
}; | |
var Snake = function(x, y) { | |
this.data = [{ | |
x: x, | |
y: y | |
}]; | |
this.direction = LEFT; | |
this.lastDirection = LEFT; | |
this.wait = 0; | |
}; | |
Snake.prototype = { | |
get head() { | |
return this.data[0]; | |
}, | |
get tail() { | |
return this.data[this.data.length - 1]; | |
}, | |
push: function(n) { | |
this.wait = n; | |
}, | |
step: function() { | |
var head = this.head; | |
var next = { | |
x: head.x, | |
y: head.y | |
}; | |
switch (this.direction) { | |
case LEFT: | |
next.x--; | |
break; | |
case RIGHT: | |
next.x++; | |
break; | |
case UP: | |
next.y--; | |
break; | |
default: | |
next.y++; | |
} | |
this.lastDirection = this.direction; | |
this.data.unshift(next); | |
if (this.wait === 0) { | |
this.data.pop(); | |
} else { | |
this.wait--; | |
} | |
} | |
}; | |
var Game = (function() { | |
var canvas = document.getElementById('canvas'), | |
context = canvas.getContext('2d'), | |
grid = new Grid(WIDTH, HEIGHT), | |
snake = new Snake(~~(WIDTH / 2), ~~(HEIGHT / 2), grid); | |
snake.push(3); | |
canvas.width = WIDTH * SIZE; | |
canvas.height = HEIGHT * SIZE; | |
var fill = function(x, y) { | |
context.fillRect(x * SIZE, y * SIZE, SIZE, SIZE); | |
}; | |
var clear = function(x, y) { | |
context.clearRect(x * SIZE, y * SIZE, SIZE, SIZE); | |
}; | |
var dot = (function() { | |
var _ = { | |
next: function() { | |
_.x = ~~(Math.random() * WIDTH); | |
_.y = ~~(Math.random() * HEIGHT); | |
while (grid.at(_.x, _.y) === 1) { | |
_.next(); | |
} | |
fill(_.x, _.y); | |
} | |
}; | |
_.next(); | |
return _; | |
})(); | |
var id = window.setInterval(render, 1000 / 20); | |
function render() { | |
var x, y; | |
if (snake.wait === 0) { | |
var tail = snake.tail; | |
x = tail.x; | |
y = tail.y; | |
clear(x, y); | |
grid.set(x, y, 0); | |
} | |
snake.step(); | |
var head = snake.head; | |
x = head.x; | |
y = head.y; | |
if (grid.at(x, y) === 1) { | |
window.clearInterval(id); | |
} | |
grid.set(x, y, 1); | |
fill(x, y); | |
if (snake.head && dot.x === snake.head.x && dot.y === snake.head.y) { | |
dot.next(); | |
snake.push(5); | |
} | |
}; | |
window.addEventListener('keydown', function(event) { | |
switch (event.which) { | |
case LEFT: | |
if (snake.lastDirection !== RIGHT) { | |
snake.direction = LEFT; | |
} | |
break; | |
case RIGHT: | |
if (snake.lastDirection !== LEFT) { | |
snake.direction = RIGHT; | |
} | |
break; | |
case UP: | |
if (snake.lastDirection !== DOWN) { | |
snake.direction = UP; | |
} | |
break; | |
case DOWN: | |
if (snake.lastDirection !== UP) { | |
snake.direction = DOWN; | |
} | |
break; | |
} | |
}); | |
})(); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment