diff --git a/game.js b/game.js index 7f91a67..5c94f7b 100644 --- a/game.js +++ b/game.js @@ -1,46 +1,70 @@ + +// set up of game canvas' along with the expected game style (2D) +// game: game state holder +// snake: snake character to be moved by user +// food: objects to be collected by snake character var canvas = document.getElementById("the-game"); var context = canvas.getContext("2d"); var game, snake, food; +// game properties game = { + // set up of starting game state + // variables are initialized to represent a new game score: 0, fps: 8, over: false, - message: null, + message: null, + - start: function() { - game.over = false; - game.message = null; - game.score = 0; + // variables are adjusted to represent the beginnning of a new game + start: function() { // starting a new game + game.over = false; // game state has been changed to in progress + game.message = null; // no message displayed to user + game.score = 0; game.fps = 8; - snake.init(); - food.set(); + snake.init(); + food.set(); }, - stop: function() { - game.over = true; - game.message = 'GAME OVER - PRESS SPACEBAR'; + + // variables are adjusted to represent the end of a game + stop: function() { // stopping a game + game.over = true; // game state has been changed to over + game.message = 'GAME OVER - PRESS SPACEBAR'; // message displayed to user notifying game has ended }, + // x: initial game board center represented by an x-coordinate + // y: initial game board center represented by a y-coordinate + // size: maximum size of the board in the x or y direction, used for both coordinates to create a square + // color: fill color of the game board drawBox: function(x, y, size, color) { context.fillStyle = color; - context.beginPath(); - context.moveTo(x - (size / 2), y - (size / 2)); - context.lineTo(x + (size / 2), y - (size / 2)); - context.lineTo(x + (size / 2), y + (size / 2)); - context.lineTo(x - (size / 2), y + (size / 2)); - context.closePath(); - context.fill(); + context.beginPath(); + context.moveTo(x - (size / 2), y - (size / 2)); // begins fill path at bottom left from centre point + context.lineTo(x + (size / 2), y - (size / 2)); // line from bottom left to bottom right + context.lineTo(x + (size / 2), y + (size / 2)); // line from bottom right to top right + context.lineTo(x - (size / 2), y + (size / 2)); // line from top right to top left + context.closePath(); // paths created are closed off + context.fill(); // area created by these lines are now filled with a solid color }, + // creates textfield for the scoreboard + // fill color of scoreboard and font of scoreboard are chosen + // scoreboard text is aligned + // scoreboard textfield filled with score and textfield dimensions are set drawScore: function() { - context.fillStyle = '#999'; - context.font = (canvas.height) + 'px Impact, sans-serif'; - context.textAlign = 'center'; + context.fillStyle = '#999'; + context.font = (canvas.height) + 'px Impact, sans-serif'; + context.textAlign = 'center'; context.fillText(game.score, canvas.width / 2, canvas.height * 0.9); }, + // creates textfield for the display messages + // fill color of display message and font of display message are chosen + // display message text is aligned + // display message textfield filled with messages and textfield dimensions are set drawMessage: function() { if (game.message !== null) { context.fillStyle = '#00F'; @@ -52,14 +76,17 @@ game = { } }, + // resets the gameboard resetCanvas: function() { context.clearRect(0, 0, canvas.width, canvas.height); } }; +// snake properties snake = { + // variables are initialized to represent a new snake size: canvas.width / 40, x: null, y: null, @@ -67,69 +94,77 @@ snake = { direction: 'left', sections: [], + // creates a new snake init: function() { - snake.sections = []; - snake.direction = 'left'; - snake.x = canvas.width / 2 + snake.size / 2; - snake.y = canvas.height / 2 + snake.size / 2; - for (var i = snake.x + (5 * snake.size); i >= snake.x; i -= snake.size) { + snake.sections = []; // array holds segements of the snake + snake.direction = 'left'; // starting direction initialized to left + snake.x = canvas.width / 2 + snake.size / 2; // starting xcoordinate for the snake + snake.y = canvas.height / 2 + snake.size / 2; // starting ycoordinate for the snake + for (var i = snake.x + (5 * snake.size); i >= snake.x; i -= snake.size) { // array tracks segements of snake via turn points snake.sections.push(i + ',' + snake.y); } }, + // snake movement move: function() { switch (snake.direction) { - case 'up': - snake.y -= snake.size; + case 'up': // when the up arrow key is pressed + snake.y -= snake.size; // moves snake in upward direction based on current size break; - case 'down': - snake.y += snake.size; + case 'down': // when the down arrow key is pressed + snake.y += snake.size; // moves snake in downward direction based on current size break; - case 'left': - snake.x -= snake.size; + case 'left': // when the left arrow key is pressed + snake.x -= snake.size; // moves snake in leftward direction based on current size break; - case 'right': - snake.x += snake.size; + case 'right': // when the right arrow key is pressed + snake.x += snake.size; // moves snake in rightward direction based on current size break; } - snake.checkCollision(); - snake.checkGrowth(); - snake.sections.push(snake.x + ',' + snake.y); + snake.checkCollision(); // collision detection + snake.checkGrowth(); // growth detection + snake.sections.push(snake.x + ',' + snake.y); // array tracks segements of snake via turn points }, + // draws all segments of the snake draw: function() { for (var i = 0; i < snake.sections.length; i++) { - snake.drawSection(snake.sections[i].split(',')); + snake.drawSection(snake.sections[i].split(',')); // concatenation of snake sections are drawn around current turn points } }, + // section: an individual section of the snake drawSection: function(section) { - game.drawBox(parseInt(section[0]), parseInt(section[1]), snake.size, snake.color); + game.drawBox(parseInt(section[0]), parseInt(section[1]), snake.size, snake.color); // snake sections are drawn individially inside the box }, + // collision detection checkCollision: function() { - if (snake.isCollision(snake.x, snake.y) === true) { - game.stop(); + if (snake.isCollision(snake.x, snake.y) === true) { // if the head of the snake collides with something + game.stop(); // game state is changed to over } }, + // x: xcoordinate for collision detection + // y: ycoordinate for collision detection isCollision: function(x, y) { - if (x < snake.size / 2 || - x > canvas.width || - y < snake.size / 2 || - y > canvas.height || + if (x < snake.size / 2 || // if snake collides with itself horizontally + x > canvas.width || // if snake collides with canvas horizontally + y < snake.size / 2 || // if snake collides with itself vertically + y > canvas.height || // if snake collides with canvas vertically snake.sections.indexOf(x + ',' + y) >= 0) { - return true; + return true; // a collision has happened } }, + // food collection, sees if the snake has collided with food checkGrowth: function() { - if (snake.x == food.x && snake.y == food.y) { - game.score++; - if (game.score % 5 == 0 && game.fps < 60) { - game.fps++; + if (snake.x == food.x && snake.y == food.y) { // if the snake head collides with a food + game.score++; // add to score + if (game.score % 5 == 0 && game.fps < 60) { + game.fps++; // increase the fps when game score increases by 5 points } - food.set(); + food.set(); // set another food on the game board } else { snake.sections.shift(); } @@ -137,32 +172,38 @@ snake = { }; +// food properties food = { + // variables are initialized to represent a new food piece size: null, x: null, y: null, color: '#0FF', + // food pieces set on the game board set: function() { food.size = snake.size; - food.x = (Math.ceil(Math.random() * 10) * snake.size * 4) - snake.size / 2; - food.y = (Math.ceil(Math.random() * 10) * snake.size * 3) - snake.size / 2; + food.x = (Math.ceil(Math.random() * 10) * snake.size * 4) - snake.size / 2; // random x-coordinate chosen for the food piece within game board dimensions + food.y = (Math.ceil(Math.random() * 10) * snake.size * 3) - snake.size / 2; // random y-coordinate chosen for the food piece within game board dimensions }, + // draws food piece on gameboard based on x-coord, y-coord, size, and color draw: function() { game.drawBox(food.x, food.y, food.size, food.color); } }; +// sets values to change directional key commands var inverseDirection = { - 'up': 'down', - 'left': 'right', - 'right': 'left', - 'down': 'up' + 'up': 'down', // up key press maps to downwards movement + 'left': 'right', // left key press maps to rightwards movement + 'right': 'left', // right key press maps to leftwards movement + 'down': 'up' // down key press maps to upwards movement }; +// sets values for directional key commands var keys = { up: [38, 75, 87], down: [40, 74, 83], @@ -171,6 +212,8 @@ var keys = { start_game: [13, 32] }; +// value: integer associated with direction key +// gets the value of directional key being pressed function getKey(value){ for (var key in keys){ if (keys[key] instanceof Array && keys[key].indexOf(value) >= 0){ @@ -180,20 +223,23 @@ function getKey(value){ return null; } +// function(e) checks for an event (a key press) to happen addEventListener("keydown", function (e) { - var lastKey = getKey(e.keyCode); - if (['up', 'down', 'left', 'right'].indexOf(lastKey) >= 0 + var lastKey = getKey(e.keyCode); // gets value of directional key + if (['up', 'down', 'left', 'right'].indexOf(lastKey) >= 0 // if a key is pressed and key direction is not inversed && lastKey != inverseDirection[snake.direction]) { - snake.direction = lastKey; - } else if (['start_game'].indexOf(lastKey) >= 0 && game.over) { - game.start(); + snake.direction = lastKey; // changes snake direction to inverse of last key pressed + } else if (['start_game'].indexOf(lastKey) >= 0 && game.over) { // waits for a key to be pressed after a game has ended + game.start(); // game state changed to begin } }, false); +// updates frames (visual display of the game) var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; +// loops through the game if game state isnt equal to over function loop() { if (game.over == false) { game.resetCanvas(); @@ -208,4 +254,4 @@ function loop() { }, 1000 / game.fps); } -requestAnimationFrame(loop); \ No newline at end of file +requestAnimationFrame(loop);