# Snake Game

## Game logic

We'll now look at the functions used for processing and logic during the game.

When we start a new game, we need to reset the game time counters and all of the gameState properties that do not persist between games to their starting values. We create a brand new, 1 block snake at the centre of the map, and place a random block of food somewhere:

``````function startGame()
{
// Reset the game time
gameTime	= 0;
lastFrameTime	= 0;

// Reset all of the gameState attributes to their
// starting values (except those that need to persist
// between games)
gameState.snake.length		= 0;
gameState.dir			= 0;
gameState.score			= 0;
gameState.lastMove		= 0;
gameState.screen		= 'playing';
gameState.newBest		= false;

// Create the snake head at the centre of the map
gameState.snake.push([
Math.floor(gameState.mapW / 2),
Math.floor(gameState.mapH / 2)
]);

// Place a random "food" block on the map
placeNewBlock();
}``````

We place the random food block on the map by finding a random coordinate on the map, and checking that coordinate isn't already occupied by the snakes body. If it is, we find somewhere else. If it isn't, we place the food here and the function is complete:

``````function placeNewBlock()
{
do {
// Choose a random coordinate somewhere on the map
var x = Math.floor(Math.random() * gameState.mapW);
var y = Math.floor(Math.random() * gameState.mapH);

// Currently we don't think this block falls on the
// snakes body
var onSnake = false;

// Loop through the snakes body segments
for(var s in gameState.snake)
{
// If this is on the snakes body, change our
// onSnake value to true
if(gameState.snake[s][0]==x &&
gameState.snake[s][1]==y)
{
onSnake = true;
break;
}
}

// If the coordinates are not on the snakes body,
// place the newBlock here and exit out of the
// loop and function
if(!onSnake)
{
gameState.newBlock = [x, y];
break;
}

// Keep trying until the block can be placed
} while(true);
}``````

Our updateGame function, which is called every frame, either looks for a click on the "New Game" text if the current screen is the menu screen. Otherwise, it runs through the update logic we discussed on the first page of this article.

``````function updateGame()
{
// Depending on the current screen being displayed, we
// handle game updates differently

{
if(mouseState.click!=null)
{
// If there's been a click on the screen and
// it falls on the "New Game" line of text,
// call the startGame function
if(mouseState.click[1] >= 150 &&
mouseState.click[1] <= 220)
{
startGame();
}
}

// Clear the click state (we've done the processing
// for it already)
mouseState.click = null;
}
else if(gameState.screen=='playing')
{
// If enough time hasn't elapsed since the snake began
// moving from the previous tile to the next, we don't
// need to do anything yet, so leave the function
if((gameTime - gameState.lastMove) < gameState.moveDelay)
{
return;
}

// Create a temporary variable storing the current
// position of the snakes head, and also the current
// direction of the snake
var tmp = gameState.snake[0];
var head = [tmp[0], tmp[1]];
var dir = gameState.dir;

// If the next position of the snakes head falls outside
// of the maps bounds, we've lost; call gameOver
if(dir==0 && head[1]==0) { gameOver(); }
else if(dir==2 && head[1]==(gameState.mapH-1)) { gameOver(); }
else if(dir==3 && head[0]==0) { gameOver(); }
else if(dir==1 && head[0]==(gameState.mapW-1)) { gameOver(); }

// Modify our head variable to the next position the
// snakes head will occupy
if(dir==0) { head[1]-= 1; }
else if(dir==2) { head[1]+= 1; }
else if(dir==1) { head[0]+= 1; }
else if(dir==3) { head[0]-= 1; }

// Loop through the snake body segments
for(var s in gameState.snake)
{
// If this is the end of the snake, ignore it
if(s==(gameState.snake.length-1)) { break; }

// If the next position of the snakes head falls
// on part of the snakes body, gameOver
{
gameOver();
break;
}
}

// If gameOver has been called, it will have changed
// the current screen.  In this case, exit the function
if(gameState.screen=='menu') { return; }

// Put the new head position on the start of the snake
// body array and update the lastMove to the current gameTime
gameState.lastMove = gameTime;

// If the new head position is the same as the food position,
// increase the score and place a random new food block.
// Otherwise, remove the tail of the snake.
{
gameState.score+= 1;
placeNewBlock();
}
else { gameState.snake.pop(); }
}
}``````

If the game is over, we change the currently displayed screen to the menu, and check the score the player has achieved. If it is more than the current high score, we flag this as a new high score and update the gameState bestScore property:

``````function gameOver()
{