tick method
void
tick()
Implementation
void tick() {
assert(!_gameCompleter.isCompleted, 'Cannot tick after game is over!');
final snakeHeadPoint = _snake.last;
final itemAtSnakeHead = _getItemAtPoint(snakeHeadPoint, _snakelessBoard);
// Update the last used direction.
_lastTickedDirection = _direction;
final nextSnakeHeadPoint = _offsetPoint(snakeHeadPoint, _direction, 1);
// If the snake head is not on food, remove the last segment.
final isOnFood = itemAtSnakeHead == SnakeItem.food;
// End the game if the next head point is off-screen.
var endGame = nextSnakeHeadPoint.y < 0 ||
nextSnakeHeadPoint.x < 0 ||
nextSnakeHeadPoint.y > _snakelessBoard.length - 1 ||
nextSnakeHeadPoint.x > _snakelessBoard[nextSnakeHeadPoint.y].length - 1;
// End the game if the next head point collides with the snake body, taking
// the last segment removal into account.
endGame = endGame ||
(_snake.contains(nextSnakeHeadPoint) &&
(isOnFood || nextSnakeHeadPoint != _snake.first));
// End the game without updating the board if any of the above conditions
// are met.
if (endGame) {
_gameCompleter.complete();
return;
}
// If the snake head is on food, remove the food.
// Otherwise, remove the last segment.
if (isOnFood) {
_setItemAtPoint(SnakeItem.empty, snakeHeadPoint, _snakelessBoard);
_ticksSinceLastAte = 0;
_ticksTillNextFood = _calculateTicksTillNextFood();
} else {
_snake.removeFirst();
}
// Add the next head point to the snake.
_snake.add(nextSnakeHeadPoint);
// If the ticks since last ate is set to -1, food is on the board waiting
// to be eaten. No further food-related action is necessary.
if (_ticksSinceLastAte != -1) {
if (_ticksSinceLastAte == _ticksTillNextFood) {
// If the timeout is complete, add food to the board.
_addFood(_random, _snakelessBoard, _snake);
_ticksSinceLastAte = -1;
} else {
// Otherwise, increment the ticks since last ate.
++_ticksSinceLastAte;
}
}
// Trigger a render.
renderer();
}