Pawel
Pawel

Reputation: 555

javascript snake game - how to move the apple?

I've wrote this simple snake game - the one where you use arrows to navigate the snake to eat apples (red circle). Right now in my code when snake eats (intersects) the apple its(snake) size increases by 1 block (10px). What I would like to do is: every time the snake eats the apple -> increase snake size -> move the apple to different position within the canvas.

inside the code I've marked the section where I think the code for moving the apple should go, but I don't know how to implement and what would be the actual code for that:

if (!this.objectCollide(myApple)){
      this.segments.pop();
    } else {
      alert("COLLISION!!"))
    }; 

here's the Full Javascript code:

var gameField = document.getElementById('gameField');
var ctx = gameField.getContext("2d");
var blockSize = 10;
columnCt = gameField.width / blockSize;
rowsCt = gameField.height / blockSize;

var block = function(x, y) {
  this.x = x;
  this.y = y;
}

block.prototype.drawBlock = function() {
  ctx.fillStyle = "blue";
  ctx.fillRect(this.x * blockSize, this.y * blockSize, blockSize,
    blockSize);
};

block.prototype.drawApple = function() {
  ctx.fillStyle = "red";
  ctx.textBaseline = "bottom";
  ctx.arc(this.x, this.y, 6, 2 * Math.PI, false);
  ctx.fill();
}

var Snake = function() {
  this.segments = [new block(20, 20), new block(19, 20), new block(18, 20), new block(17, 20),
    new block(16, 20), new block(15, 20), new block(14, 20), new block(13, 20), new block(12, 20),
    new block(11, 20), new block(10, 20)
  ];
  this.direction = "right";
}

Snake.prototype.drawSnake = function() {
  for (i = 0; i < this.segments.length; i++) {
    this.segments[i].drawBlock();
  }
}

Snake.prototype.setDirection = function(dir) {
  if (this.direction == "left" && dir == "right" || this.direction == "right" && dir == "left" || this.direction == "up" && dir == "down" ||
    this.direction == "down" && dir == "up") {
    return
  } else {
    this.direction = dir;
  };
};

Snake.prototype.objectCollide = function(obj) {
  if (this.segments[0].x == Math.round(obj.x / blockSize) && this.segments[0].y == Math.round(obj.y / blockSize)) {
    return true
  } else {
    return false
  }
};

Snake.prototype.move = function() {
  var head = this.segments[0];
  var newHead;

  switch (this.direction) {
    case "right":
      newHead = new block(head.x + 1, head.y);
      break;
    case "left":
      newHead = new block(head.x - 1, head.y)
      break;
    case "down":
      newHead = new block(head.x, head.y + 1)
      break;
    case "up":
      newHead = new block(head.x, head.y - 1)
      break;
  }

  this.segments.unshift(newHead);

  if (!this.objectCollide(myApple)) {
    this.segments.pop();
  } else {
    alert("COLLISION!!!")
  };
  var collision = newHead.x >= columnCt || newHead.x <= -1 ||
    newHead.y >= rowsCt || newHead.y <= -1;

  for (i = 1; i < this.segments.length; i++) {
    if (this.segments[i].x == newHead.x && this.segments[i].y == newHead.y) {
      collision = true;
      break;
    };
  };

  if (collision) {
    clearInterval(myFun);
  };

};

var mySnake = new Snake()
mySnake.drawSnake();
var myApple = new block(Math.floor(Math.random() * gameField.width),
  Math.floor(Math.random() * gameField.height));
var myFun = setInterval(function() {
  ctx.clearRect(0, 0, gameField.width, gameField.height);
  mySnake.move();
  mySnake.drawSnake();
  myApple.drawApple();
}, 100)

var directions = {
  37: "left",
  38: "up",
  39: "right",
  40: "down"
};

document.onkeydown = function(event) {
  var newDirection = directions[event.keyCode]
  if (newDirection != undefined) {
    mySnake.setDirection(newDirection);
  };
};

And example on JSFiddle: https://jsfiddle.net/x9ztn3vs/

Upvotes: 0

Views: 1157

Answers (1)

lilezek
lilezek

Reputation: 7364

Instead of using alert("COLLISION!!!"); just do these two things:

Increasing the size of the snake

Just add another element to the array at the end:

this.segments.push(this.segments[this.segments.length-1]);

Moving around the apple

do {
    myApple.x = Math.floor(Math.random() * gameField.width);
    myApple.y = Math.floor(Math.random() * gameField.height);
    var colliding = this.segments.find((v) => v.x == Math.round(myApple.x / blockSize) && v.y == Math.round(myApple.y / blockSize));    
} while (colliding);

Disclaimer: it is not efficient. It will lag as the snake's length will increase because the probability of collision.

Upvotes: 2

Related Questions