Snake

For this weeks assignment I decided to create the popular Snake game. In the creative process I tried to optimize it and I am quite happy with the results. I created a simple class for a snake element and then reused it while creating food items.

To make the game even more optimized I decided to draw the snake in a specific fashion. When the snake eats their food, the food is not “added” to it. Rather than that, the last part of the snake is not removed from it a single time, as it would usually be. That makes the transition a lot smoother and also makes the code cleaner.

With regard to the hit boxes I made them simple as the game was designed on a 10px grid. As a result the snake elements are 10px/10px. Due to that, I could simply compare the X and Y dimensions of the Snake’s leading tile against food’s location, rather than comparing whole ranges, which would be much less efficient.

class snakeRect {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

score = 0;
food = new snakeRect(-10,-10);
vx = -10;
vy = 0;

snake = [new snakeRect(200, 200),
         new snakeRect(210, 200),
         new snakeRect(220, 200),
         new snakeRect(230, 200),
        ];

function setup() {
  createCanvas(400, 400);
  textSize(50);
  food.x = round(random(0, (width-10)/10))*10;
  food.y = round(random(0, (height-10)/10))*10;
}

function draw() {
  background(220);
  fill(255);
  textAlign(LEFT);
  text(score, 20, 50);
  if (isGameOver()){   
    textAlign(CENTER);
    translate(width/2, height/2);
    fill(255);
    text('Game Over', 0, 0);
    return;
  }
  
  drawSnake();
  drawFood();

  if (frameCount%5==0) {
    moveSnake();
  }
}

function getFood() {
  randX = round(random(0, (width-10)/10))*10;
  randY = round(random(0, (height-10)/10))*10;
  
  for(i=0; i<snake.length; i++) {
    if (snake[i].x==randX && snake[i].y==randY) {
      getFood();
    }
  }
  
  food.x = randX;
  food.y = randY;
}

function drawFood() {
  fill(255, 255, 0);
  rect(food.x, food.y, 10, 10);
}

function drawSnake() { 
  fill(200,200,0);
  for (i=0; i<snake.length; i++) {
      rect(snake[i].x, snake[i].y, 10, 10);  
  }
}

function moveSnake() { 
  newElem = new snakeRect(snake[0].x+vx, snake[0].y+vy);
  snake.unshift(newElem);

  if (snake[0].x === food.x && snake[0].y === food.y) {
    score+=10;
    getFood();
  }
  else {
    snake.pop();
  }
}

function keyPressed() {
  if (keyCode===LEFT_ARROW && vx!=10) {
    vx=-10;
    vy=0;
  }
  else if (keyCode === RIGHT_ARROW && vx!=-10) {
    vx=10;
    vy=0;
  }
  else if (keyCode === UP_ARROW && vy!=10) {
    vx=0;
    vy=-10;
  }
  else if (keyCode === DOWN_ARROW && vy!=-10) {
    vx=0;
    vy=10;
  }
}

function isGameOver() {  
  for (i=4; i<snake.length; i++)
  {    
    if (snake[i].x === snake[0].x && snake[i].y === snake[0].y) {
      return true;
    }
  }
  return snake[0].x<0 ||  snake[0].x>width-10 || snake[0].y<0 || snake[0].y>height-10;
}

 

Leave a Reply