Search code examples
javascripthtml5-canvas

Why the code doesn't work when the snake eats the apple?


Good afternoon everyone. I was making my own snake game. And when I implemented the snake eating function, I ran into a problem (The function that should start while the snake is eating the apple doesn't work.)

I tried to equate the positions of the apple to the size of the block. And the function should return me an alert when the snake has eaten the apple.

var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
var box = 10;

//Snake
var snake = [];
var px = canvas.width / 2;
var py = canvas.height / 2;
var dir = "right";
var maxCell = 10;
var can = canvas.getBoundingClientRect();

//Apple
var ax = Math.floor(Math.random() * ~~(canvas.width / box));
var ay = Math.floor(Math.random() * ~~(canvas.height / box));

document.addEventListener("keydown", function(e) {
  if (e.keyCode === 37 && dir !== "right") {
    dir = "left";
    //console.log('left')
  } else if (e.keyCode === 38 && dir !== "down") {
    dir = "up";
    //console.log('up')
  } else if (e.keyCode === 39 && dir !== "left") {
    dir = "right";
    //console.log('right')
  } else if (e.keyCode === 40 && dir !== "up") {
    dir = "down";
    //console.log('down')
  }
});

function direction() {
  if (dir == "right") {
    px += box;
  } else if (dir == "left") {
    px -= box;
  } else if (dir == "up") {
    py -= box;
  } else if (dir == "down") {
    py += box;
  }
}

//Closure )))
function Elems() {
  //! Spawn apple
  function Apple() {
    ctx.fillStyle = "green";
    ctx.fillRect(ax, ay, box, box);
  }

  //! Spawn snake
  function Snake() {
    direction();
    var head = {
      x: px,
      y: py,
    };
    snake.unshift(head);

    if (snake.length < maxCell) {
      snake.push({
        x: px,
        y: py
      });
    }

    if (px >= canvas.width) {
      px = 0;
    } else if (px < 0) {
      px = canvas.width;
    }
    if (py >= canvas.height) {
      py = 0;
    } else if (py < 0) {
      py = canvas.height;
    }
    snake.forEach(function(elem, index) {
      ctx.fillStyle = `red`;
      ctx.fillRect(elem.x, elem.y, box, box);
    });

    //BROKEN CODE
    if (head.x == ax && head.y == ay) {
      alert("HI");
    }
    snake.pop();
  }

  Snake();
  Apple();
}

function loop() {
  setInterval(() => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    Elems();
  }, 2000 / 30);
}

loop();
canvas {
  border: 1px solid #000;
  background-color: #000;
}
<canvas id="game" width="450" height="450"></canvas>


Solution

  • You need to calculate your grid if you box is 10x10 . In your case you have 450 x 450px canvas you divide that by 10 and the grid will be 45x45

    Use grid.x and grid.y (those are your max values in you grid) to place the snake and generate an apple coords.

    That way you need to check only top left coords and not if rectangles overlap

    var canvas = document.getElementById("game");
    var ctx = canvas.getContext("2d");
    var box = 10;
    //calculate your grid
    var grid = {
      x: Math.floor(canvas.width / box),
      y: Math.floor(canvas.height / box)
    };
    
    var snake = [];
    //use grid to center the snake
    var px = Math.floor(grid.x / 2) * box;
    var py = Math.floor(grid.y / 2) * box;
    var dir = "right";
    var maxCell = 10;
    var can = canvas.getBoundingClientRect();
    
    //Apple
    //use your grid to spawn an apple
    var ax = Math.floor(Math.random() * grid.x) * box;
    var ay = Math.floor(Math.random() * grid.y) * box;
    
    document.addEventListener("keydown", function(e) {
      if (e.keyCode === 37 && dir !== "right") {
        dir = "left";
        //console.log('left')
      } else if (e.keyCode === 38 && dir !== "down") {
        dir = "up";
        //console.log('up')
      } else if (e.keyCode === 39 && dir !== "left") {
        dir = "right";
        //console.log('right')
      } else if (e.keyCode === 40 && dir !== "up") {
        dir = "down";
        //console.log('down')
      }
    });
    
    function direction() {
      if (dir == "right") {
        px += box;
      } else if (dir == "left") {
        px -= box;
      } else if (dir == "up") {
        py -= box;
      } else if (dir == "down") {
        py += box;
      }
    }
    
    //Closure )))
    function Elems() {
      //! Spawn apple
      function Apple() {
        ctx.fillStyle = "green";
        ctx.fillRect(ax, ay, box, box);
      }
    
      //! Spawn snake
      function Snake() {
        direction();
        var head = {
          x: px,
          y: py,
        };
        snake.unshift(head);
    
        if (snake.length < maxCell) {
          snake.push({
            x: px,
            y: py
          });
        }
    
        if (px >= canvas.width) {
          px = 0;
        } else if (px < 0) {
          px = canvas.width;
        }
        if (py >= canvas.height) {
          py = 0;
        } else if (py < 0) {
          py = canvas.height;
        }
        snake.forEach(function(elem, index) {
          ctx.fillStyle = `red`;
          ctx.fillRect(elem.x, elem.y, box, box);
        });
        //BROKEN CODE
        if (head.x == ax && head.y == ay) {
          alert("HI");
        }
        snake.pop();
      }
    
      Snake();
      Apple();
    }
    
    function loop() {
      setInterval(() => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        Elems();
      }, 2000 / 30);
    }
    
    loop();
    canvas {
      border: 1px solid #000;
      background-color: #000;
    }
    <canvas id="game" width="450" height="450"></canvas>