Reza Saadati
Reza Saadati

Reputation: 5429

Let the snake catch his food

I am trying to create a simple snake game. For now I am trying to catch the food but the position of the snake is never the same as the position of food.

(function() {
      var canvas = document.getElementById('canvas'),
          ctx = canvas.getContext('2d'),
          x = 0,
          y = 0,
          speed = 2; 
          x_move = speed,
          y_move = 0,                          
          food_position_x = Math.floor(Math.random() * canvas.width);
          food_position_y = Math.floor(Math.random() * canvas.height);
    
      function eat() {   
       console.log('food_x:' + food_position_x + ' x:' + x + ' / food_y:' + food_position_y + ' y:' + y);
        if (y == food_position_y && x == food_position_x) {       
          throw new Error("MATCH!"); // This is not an error. Just trying to stop the script
        }
      }
      
      // Drawing
      function draw() {
        eat();
        requestAnimationFrame(function() {      
          draw();      
        });    
        // Draw the snake
        ctx.beginPath();
        ctx.rect(Math.floor(x/10)*10, Math.floor(y/10)*10, 10, 10);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#ffffff'; 
        ctx.fill();
        ctx.closePath();
    
        // Draw the food
        ctx.beginPath(); 
        ctx.rect(Math.floor(food_position_x/10)*10, Math.floor(food_position_y/10)*10, 10, 10);
        ctx.fillStyle = "blue";
        ctx.fill();
        ctx.closePath();
    
        // Increase the value of x and y in order to animate
        x = x + x_move;
        y = y + y_move;       
      } 
      draw();
    
      // Key Pressing
      document.addEventListener('keydown', function(event) {
        switch(event.keyCode) {
          case 40: // Moving down
            if (x_move != 0 && y_move != -1) {
              x_move = 0;
              y_move = speed;
            }
          break;
          case 39: // Moving right
            if (x_move != -1 && y_move != 0) {
              x_move = speed;
              y_move = 0; 
            }
          break;
          case 38: // Moving top
            if (x_move != 0 && y_move != 1) {
              x_move = 0;
              y_move = -speed; 
            }
          break;
          case 37: // Moving left
            if (x_move != 1 && y_move != 0) {
              x_move = -speed;
              y_move = 0; 
            }
          break;
        }
      });
    })();
canvas { background-color: #000022 }
<canvas id="canvas" width="400" height="400"></canvas>

console.log() will return all positions.

jsfiddle

Am I calculating something wrong? Maybe I have to change the variables food_position_x and food_position_y. If not, I have no idea why the positions are never the same.

Upvotes: 7

Views: 153

Answers (3)

Kirill Simonov
Kirill Simonov

Reputation: 8491

Your game area is supposed to be a grid of cells with widths and heights of 10. That's why you do this: Math.floor(x/10)*10 when drawing the snake.

To make the eat function work you just need to draw the food in the same way:

food_position_x = Math.floor(Math.random() * canvas.width / 10) * 10;
food_position_y = Math.floor(Math.random() * canvas.height / 10) * 10;

and add the same thing to the if condition of the eat function:

if (Math.floor(y/10)*10 == food_position_y && Math.floor(x/10)* 10 == food_position_x)

(function() {
      var canvas = document.getElementById('canvas'),
          ctx = canvas.getContext('2d'),
          x = 0,
          y = 0,
          speed = 2; 
          x_move = speed,
          y_move = 0,                          
          food_position_x = Math.floor(Math.random() * canvas.width / 10) * 10;
          food_position_y = Math.floor(Math.random() * canvas.height / 10) * 10;
    
      function eat() {   
       //console.log('food_x:' + food_position_x + ' x:' + x + ' / food_y:' + food_position_y + ' y:' + y);
        if (Math.floor(y/10)*10 == food_position_y && Math.floor(x/10)* 10 == food_position_x) {       
          throw new Error("MATCH!"); // This is not an error. Just trying to stop the script
        }
      }
      
      // Drawing
      function draw() {
        eat();
        requestAnimationFrame(function() {      
          draw();      
        });
        // Increase the value of x and y in order to animate
        x = x + x_move;
        y = y + y_move;   
        if (x > canvas.width) x = 0;
        if (y > canvas.height) y = 0;
        if (y < 0) y = canvas.height;
        if (x < 0) x = canvas.width;
        // Draw the snake
        ctx.beginPath();
        ctx.rect(Math.floor(x/10)*10, Math.floor(y/10)*10, 10, 10);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#ffffff'; 
        ctx.fill();
        ctx.closePath();
    
        // Draw the food
        ctx.beginPath(); 
        ctx.rect(Math.floor(food_position_x/10)*10, Math.floor(food_position_y/10)*10, 10, 10);
        ctx.fillStyle = "blue";
        ctx.fill();
        ctx.closePath();  
      } 
      draw();
    
      // Key Pressing
      document.addEventListener('keydown', function(event) {
        switch(event.keyCode) {
          case 40: // Moving down
            if (x_move != 0 && y_move != -1) {
              x_move = 0;
              y_move = speed;
            }
          break;
          case 39: // Moving right
            if (x_move != -1 && y_move != 0) {
              x_move = speed;
              y_move = 0; 
            }
          break;
          case 38: // Moving top
            if (x_move != 0 && y_move != 1) {
              x_move = 0;
              y_move = -speed; 
            }
          break;
          case 37: // Moving left
            if (x_move != 1 && y_move != 0) {
              x_move = -speed;
              y_move = 0; 
            }
          break;
        }
      });
    })();
canvas { background-color: #000022 }
<canvas id="canvas" width="400" height="400"></canvas>

Upvotes: 3

Ben West
Ben West

Reputation: 4596

Your game looks like it's on big chunky grid, but it really isn't, that's only in the graphics. The state variables, which are what matter, are little fiddly small numbers.

Instead of drawing the snake like this:

ctx.rect(Math.floor(x/10)*10, Math.floor(y/10)*10, 10, 10);

Try drawing it like this:

ctx.rect( x, y, 1, 1 );

And you'll see the real state of the game. This is what you're really playing: https://jsfiddle.net/xeyrmsLc/11/ - and that's why it's hard to get the food.

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 371089

The main problem is that there are so many possibilities for x and food_position_x, and precise control is difficult, that it's very difficult to land exactly on an X that matches in combination with a Y that matches. You have to move back and forth a lot around the same area to get an exact match for X or an exact match for Y (from which you can then proceed to go in some orthogonal direction to land on the food).

But your code does work at a base level. You might consider reducing the speed and making the visual square location exactly match the internal numbers (less visual granularity which doesn't match the underlying state).

Upvotes: 0

Related Questions