Added variable growth factor and groundwork for victory conditions.

This commit is contained in:
Jonathan Bernard 2014-12-12 05:02:18 -06:00
parent 104a0f9957
commit cb1db47704

View File

@ -16,11 +16,17 @@
// The starting game board. // The starting game board.
var startBoard; var startBoard;
var startGrowthFactor = 2; // When we eat food, how many turns do we grow?
var startGFIncrease=0; // When we eat, how much should the GF increase?
var targetScore = 0; // How many pieces of food must we eat to win?
var body = new Array(); var body = new Array(); // Queue of body indices.
var headCur; var headCur; // Index of the head's current position.
var direction = 1; var direction = 1; // Current movement direction.
var foodEaten = false; var foodEaten = false; // Did we eat food this turn?
var growthFactor // When we eat food, how many turns do we grow?
var growthCounter; // How many remaining turns should we grow?
var score = 0; // How many pieces of food have we eaten?
// HTML Elements // HTML Elements
var canvas; var canvas;
@ -49,6 +55,8 @@
function initialize(options) { function initialize(options) {
if (!options) options = {};
// Store our own copy of the canvas and get a 2D graphics context. // Store our own copy of the canvas and get a 2D graphics context.
if (options.canvas) canvas = options.canvas; if (options.canvas) canvas = options.canvas;
else canvas = document.getElementsByTagName("canvas")[0]; else canvas = document.getElementsByTagName("canvas")[0];
@ -75,14 +83,32 @@
else startBoard[i] = SPACE; } } else startBoard[i] = SPACE; } }
// Figure out how big each game tile is. // Figure out how big each game tile is.
tileWidth = canvas.width / COLS; tileWidth = Math.ceil(canvas.width / COLS);
tileHeight = canvas.height / ROWS; tileHeight = Math.ceil(canvas.height / ROWS);
console.log("canvas.width: " + canvas.width);
console.log("canvas.height: " + canvas.height);
console.log("ROWS: " + ROWS);
console.log("COLS: " + COLS);
console.log("Tile Width: " + tileWidth);
console.log("Tile Height: " + tileHeight);
// Mark the player as dead. This is primarily for the case where a // Mark the player as dead. This is primarily for the case where a
// player re-initializes the board during a game in progress. It // player re-initializes the board during a game in progress. It
// causes any scheduled logic to quit without affecting out game state. // causes any scheduled logic to quit without affecting out game state.
dead = true; dead = true;
// Read in the growth factor and increase.
if (options.growthFactor) startGrowthFactor = options.growthFactor;
else startGrowthFactor = 2;
if (options.growthFactorIncrease)
startGFIncrease = options.growthFactorIncrease;
else startGFIncrease = 1;
// Check for a target score to consider this level "won."
if (options.targetScore) targetScore = option.targetScore;
else options.targetScore = 0; // 0 = no target, play indefinitely.
// Check to see if they want to use the editor or the game. // Check to see if they want to use the editor or the game.
editor = Boolean(options.editor); editor = Boolean(options.editor);
@ -96,7 +122,7 @@
g.font = "24px sans-serif"; g.font = "24px sans-serif";
g.fillStyle = "black"; g.fillStyle = "black";
g.fillText("Press Enter to begin.", 50, Math.floor(canvas.height/2), canvas.width - 100); g.fillText("Press Space to begin.", 50, Math.floor(canvas.height/2), canvas.width - 100);
if (options.fps) skipTicks = Math.ceil(1000 / options.fps); if (options.fps) skipTicks = Math.ceil(1000 / options.fps);
else skipTicks = 150; } else skipTicks = 150; }
@ -113,26 +139,30 @@
canvas.focus(); } canvas.focus(); }
function startGame() { function startGame() {
while (body.length > 0) body.pop(); while (body.length > 0) body.pop();
while (cmdQueue.length > 0) cmdQueue.pop(); while (cmdQueue.length > 0) cmdQueue.pop();
headCur = coord2idx(Math.floor((ROWS - 1) / 2), Math.floor((COLS - 1) / 2));
direction = 1; direction = 1;
dead = pause = false; dead = pause = false;
score = growthCounter = 0;
nextGameTick = (new Date).getTime() + skipTicks; nextGameTick = (new Date).getTime() + skipTicks;
growthFactor = startGrowthFactor;
body.push(headCur); growthFactorIncrease = startGFIncrease;
// Copy over a fresh board. // Copy over a fresh board.
board = new Array(startBoard.length); board = new Array(startBoard.length);
for (var i = 0; i < board.length; i++) board[i] = startBoard[i]; for (var i = 0; i < board.length; i++) board[i] = startBoard[i];
// Create a new food item and add it to the board. // Create a new food item and add it to the board.
board[newFoodLocation()] = FOOD; board[randomEmptySpace()] = FOOD;
// Write the initial body segment onto the board. // Find or write the initial body segment onto the board.
for (headCur = -1, i = 0; i < board.length; i++)
if (board[i] == SNAKE) headCur = i;
if (headCur < 0) headCur = randomEmptySpace();
body.push(headCur);
board[headCur] = SNAKE; board[headCur] = SNAKE;
// Draw the board // Draw the board
@ -195,13 +225,17 @@
// 3. First check to see if we've eaten food (since it will affect // 3. First check to see if we've eaten food (since it will affect
// collision detection for the body). This is also where growth // collision detection for the body). This is also where growth
// happens via not moving the tail. // happens via not moving the tail.
if (board[headCur] == FOOD) foodEaten = true; if (board[headCur] == FOOD) {
foodEaten = true;
growthCounter += growthFactor;
growthFactor += growthFactorIncrease; }
// 4. Remove the tail. // 4. Remove the tail.
if (!foodEaten) { if (growthCounter == 0) {
var tailIdx = body.shift(); var tailIdx = body.shift();
board[tailIdx] = SPACE board[tailIdx] = SPACE
paintIdx(tailIdx); } paintIdx(tailIdx); }
else growthCounter -= 1;
// 5. Detect wall and snake collisions // 5. Detect wall and snake collisions
if (board[headCur] == WALL || board[headCur] == SNAKE) { if (board[headCur] == WALL || board[headCur] == SNAKE) {
@ -214,12 +248,12 @@
// 7. Create more food if needed. // 7. Create more food if needed.
if (foodEaten) { if (foodEaten) {
var foodLoc = newFoodLocation(); var foodLoc = randomEmptySpace();
board[foodLoc] = FOOD; board[foodLoc] = FOOD;
paintIdx(foodLoc); } } paintIdx(foodLoc); } }
// Find a new location for a piece of food. // Find a new location for a piece of food.
function newFoodLocation() { function randomEmptySpace() {
// Find all the spaces on the board that are not occupied // Find all the spaces on the board that are not occupied
var emptySpaces = new Array(); var emptySpaces = new Array();
for (var i = 0; i < board.length; i++) for (var i = 0; i < board.length; i++)
@ -236,7 +270,7 @@
g.font = "24px sans-serif"; g.font = "24px sans-serif";
g.fillStyle = "red"; g.fillStyle = "red";
g.fillText("Press Enter to retry.", 50, Math.floor(canvas.height/2), canvas.width - 100); } g.fillText("Press Space to retry.", 50, Math.floor(canvas.height/2), canvas.width - 100); }
function handleGameKey(ke) { function handleGameKey(ke) {
var key = ke.keyCode ? ke.keyCode : ke.which; var key = ke.keyCode ? ke.keyCode : ke.which;
@ -245,8 +279,8 @@
// worrying about the game becoming a black-hole for events. // worrying about the game becoming a black-hole for events.
var dontCare = false; var dontCare = false;
// Enter, start a new game. // Space, start a new game.
if (key == 13) { if (key == 32) {
dead = true; dead = true;
requestAnimationFrame(startGame); } requestAnimationFrame(startGame); }
@ -279,8 +313,8 @@
var dontCare = false; var dontCare = false;
switch (key) { switch (key) {
// Enter: place a tile. // Space or Enter: place a tile.
case 13: board[cursorIdx] = cursorBlock; break; case 32: case 13: board[cursorIdx] = cursorBlock; break;
// Direction keys: move the cursor. // Direction keys: move the cursor.
case 37: cursorIdx -= 1; break; // Left case 37: cursorIdx -= 1; break; // Left
@ -323,6 +357,9 @@
board: board, board: board,
rows: ROWS, rows: ROWS,
cols: COLS, cols: COLS,
growthFactor: startGrowthFactor,
growthFactorIncrease: startGFIncrease,
targetScore: targetScore,
fps: Math.ceil(1000 / skipTicks)}); } fps: Math.ceil(1000 / skipTicks)}); }
// Load the editor data as a JSON string from the textarea. // Load the editor data as a JSON string from the textarea.