I recently followed a tutorial on a JavaScript snake game. I tried to improve that game by adding bad fruit which will make your snakes tail incredibly long.
//constants
var COLS = 26,
ROWS = 26;
//IDs
var EMPTY = 0,
SNAKE = 1,
FRUIT = 2,
BADFRUIT = 3;
//direction
var LEFT = 0,
UP = 1,
RIGHT = 2,
DOWN = 3;
//game objects
var canvas, ctx, keystate, frames;
// Key Codes
var KEY_LEFT = 37,
KEY_UP = 38,
KEY_RIGHT = 39,
KEY_DOWN = 40
var grid = {
width: null,
height: null,
_grid: null,
init: function(d, c, r) {
this.width = c;
this.height = r;
this._grid = [];
for (var x = 0; x < c; x++) {
this._grid.push([]);
for (var y = 0; y < r; y++) {
this._grid[x].push(d);
}
}
},
set: function(val, x, y) {
this._grid[x][y] = val;
},
get: function(x, y) {
return this._grid[x][y]
},
}
var snake = {
direction: null,
last: null,
_queue: null,
init: function(d, x, y) {
this.direction = d;
this._queue = [];
this.insert(x, y);
},
insert: function(x, y) {
// unshift prepends an element to an array
this._queue.unshift({
x: x,
y: y
});
this.last = this._queue[0];
},
remove: function() {
return this._queue.pop();
},
}
function setAlwaysBadFood() {
var empty = [];
for (var x = 0; x < grid.width; x++) {
for (var y = 0; y < grid.height; y++) {
if (grid.get(x, y) === EMPTY) {
empty.push({
x: x,
y: y
});
}
}
}
var randpos = empty[Math.round(Math.random() * (empty.length - 1))];
grid.set(BADFRUIT, randpos.x, randpos.y);
}
function setBadFood() {
var randomBadFruit = Math.round(Math.random() * 10)
console.log(randomBadFruit)
console.log("WHY ARE YOU LOOKING HERE! >:(")
if (randomBadFruit === 9 || randomBadFruit === 8) {
var empty = [];
for (var x = 0; x < grid.width; x++) {
for (var y = 0; y < grid.height; y++) {
if (grid.get(x, y) === EMPTY) {
empty.push({
x: x,
y: y
});
}
}
}
var randpos = empty[Math.round(Math.random() * (empty.length - 1))];
grid.set(BADFRUIT, randpos.x, randpos.y);
console.log(randomBadFruit)
}
}
function setFood() {
var empty = [];
for (var x = 0; x < grid.width; x++) {
for (var y = 0; y < grid.height; y++) {
if (grid.get(x, y) === EMPTY) {
empty.push({
x: x,
y: y
});
}
}
}
var randpos = empty[Math.round(Math.random() * (empty.length - 1))];
grid.set(FRUIT, randpos.x, randpos.y);
}
function main() {
canvas = document.createElement("canvas");
canvas.width = COLS * 35;
canvas.height = ROWS * 35;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
frames = 0
keystate = {};
document.addEventListener("keydown", function(evt) {
keystate[evt.keyCode] = true;
});
document.addEventListener("keyup", function(evt) {
delete keystate[evt.keyCode];
});
init();
loop();
}
function init() {
grid.init(EMPTY, COLS, ROWS);
var sp = {
x: Math.floor(COLS / 2),
y: ROWS - 1
};
snake.init(UP, sp.x, sp.y);
grid.set(SNAKE, sp.x, sp.y);
setBadFood();
setFood();
}
function loop() {
update();
draw();
window.requestAnimationFrame(loop, canvas);
}
function update() {
frames++;
if (keystate[KEY_LEFT] && snake.direction !== RIGHT) {
snake.direction = LEFT;
}
if (keystate[KEY_UP] && snake.direction !== DOWN) {
snake.direction = UP;
}
if (keystate[KEY_RIGHT] && snake.direction !== LEFT) {
snake.direction = RIGHT;
}
if (keystate[KEY_DOWN] && snake.direction !== UP) {
snake.direction = DOWN;
}
if (frames % 5 === 0) {
var nx = snake.last.x
var ny = snake.last.y
switch (snake.direction) {
case LEFT:
nx--;
break;
case UP:
ny--;
break;
case RIGHT:
nx++;
break;
case DOWN:
ny++;
break;
}
if (0 > nx || nx > grid.width - 1 ||
0 > ny || ny > grid.height - 1 ||
grid.get(nx, ny) === SNAKE
) {
return init();
}
if (grid.get(nx, ny) === BADFRUIT) {
var tail = {
x: nx,
y: ny
};
for (var i = 0; i < 50; i++) {
snake.insert(tail.x, tail.y);
}
for (var i = 0; i < 10; i++) {
setAlwaysBadFood();
}
}
if (grid.get(nx, ny) === FRUIT) {
var tail = {
x: nx,
y: ny
};
snake.insert(tail.x, tail.y);
snake.insert(tail.x, tail.y);
snake.insert(tail.x, tail.y);
setFood();
setBadFood();
setAlwaysBadFood();
} else {
var tail = snake.remove();
grid.set(EMPTY, tail.x, tail.y);
tail.x = nx;
tail.y = ny;
}
grid.set(SNAKE, tail.x, tail.y);
snake.insert(tail.x, tail.y);
}
}
function draw() {
// calculate tile-width and -height
var tw = canvas.width / grid.width;
var th = canvas.height / grid.height;
// iterate through the grid and draw all cells
for (var x = 0; x < grid.width; x++) {
for (var y = 0; y < grid.height; y++) {
// sets the fillstyle depending on the id of
// each cell
switch (grid.get(x, y)) {
case EMPTY:
ctx.fillStyle = "#fff";
break;
case SNAKE:
ctx.fillStyle = "#0ff";
break;
case FRUIT:
ctx.fillStyle = "#f00";
break;
case BADFRUIT:
ctx.fillStyle = "#000066"
}
ctx.fillRect(x * tw, y * th, tw, th);
}
}
}
// start and run the game
main();
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Snake Game</title>
<style>
canvas {
display: block;
position: absolute;
border: 1px solid #000;
margin: 0;
top: 0 bottom: 0 right: 0 left: 0;
}
</style>
</head>
<body>
<script>
</script>
</body>
What do you think? I'm trying to make the snake go faster but I can't do that. I don't know what happend but the controls do not work in the stack snippet sorry for that!
-
1\$\begingroup\$ You can convert this into Stack Snippets in your post. \$\endgroup\$Joseph– Joseph2016年01月27日 18:40:35 +00:00Commented Jan 27, 2016 at 18:40
-
\$\begingroup\$ @JosephtheDreamer i did that but now the controls don't work ): \$\endgroup\$LVsuper– LVsuper2016年01月27日 19:01:53 +00:00Commented Jan 27, 2016 at 19:01
1 Answer 1
i would use let
instead of var
, and the syntax update(){}
instead of function: update(){}
(considering the ES6 standard).
-
\$\begingroup\$ There is nothing in this question indicating that the author is targeting ECMAScript 6. \$\endgroup\$200_success– 200_success2016年01月29日 17:57:06 +00:00Commented Jan 29, 2016 at 17:57
-
\$\begingroup\$ i'm new to SO, this type of answers is wrong? It's a way of improve his code isn't? @200_success \$\endgroup\$Josenberg– Josenberg2016年01月29日 18:21:12 +00:00Commented Jan 29, 2016 at 18:21