【问题标题】:Snake food collision detection蛇食碰撞检测
【发布时间】:2021-08-31 07:07:46
【问题描述】:

我正在用纯 JavaScript 制作蛇游戏。但现在我已经来到了游戏的食物部分。但我就是不能让它正常工作。我有一个食物功能,可以在游戏场内生成随机绳索,然后绘制食物。这在第一时间就已经很不靠谱了。但后来我想检测蛇绳和食物绳与 20px 的边距匹配。但我就是不能把它说得通顺。

谁能帮我找出问题所在以及如何解决这个问题?谢谢!

    let canvas = document.getElementById("canvas");
    let movespeedX = 2;
    let movespeedY = 0;
    var canvasContext = canvas.getContext('2d');
    
    //newest cord
    let locationX = 20;
    let locationY = 20;
    //cords up to snakelength
    let cords = [
        {X: 5, Y: 5}
    ];

    let snakeLength = 5;
    
    //food location
    let foodX;
    let foodY;
    let isfood = false;

    //onload draw, move and set food
    window.onload = function() {
    setInterval(callField => {draw(); move(); food()}, 1000/60);

    //keyboard controls
    document.addEventListener('keydown', event => {
        const key = event.key.toLowerCase();
        if(key == "w" || key == "arrowup")
        {
            movespeedX = 0;
            movespeedY = -2;
        }
        if(key == "s" || key == "arrowdown")
        {
            movespeedX = 0;
            movespeedY = 2;
        }
        if(key == "a" || key == "arrowleft")
        {
            movespeedY = 0;
            movespeedX = -2;
        }
        if(key == "d" || key == "arrowright")
        {
            movespeedY = 0;
            movespeedX = 2;
        }
    });
    }

    function move()
    {
        //add movespeed to location to move all directions
        locationX += movespeedX;
        locationY += movespeedY;

        //if a wall is hit restart
        if(cords[0].X >= canvas.width || cords[0].X <= 0 || cords[0].Y >= canvas.height || cords[0].Y < 0)
        {
            restart();
        }

        //if food is hit with 20px margin (this is currently verry trippy and does not work)
        if(foodY+20 > cords[0].X && foodY+20 > cords[0].Y)
        {
            isfood = false;
            snakeLength += 5;
        }
        
        //update cords array with newest location
        cords.unshift({X: locationX, Y: locationY});
        if(cords.length > snakeLength)
        {
            delete cords[snakeLength];
        }
    }

    function draw()
    {
        //draw canvas
        drawRect(0,0,canvas.width,canvas.height,"black");
        //draw food
        drawCircle(foodX, foodY, 20, "red");
        //draw snake
        cords.forEach(element => {
            drawCircle(element.X+20,element.Y,20,"white");
        });
    }
   
    //reset to standard values
    function restart()
    {
        locationX = 20;
        locationY = 20;
        movespeedX = 0;
        movespeedY = 0;
        snakeLength = 1;
        cords = [
            {X: 0, Y: 0}
        ];
    }

    //if the is no food, generate new cords and set food to true
    function food()
    {
        if(isfood === false)
        {
            foodX = Math.floor(Math.random() * canvas.width) + 50;
            foodY = Math.floor(Math.random() * canvas.height) + 50;
            isfood = true;
        }
    }
   
    function drawRect(leftX, topY, width, height, color)
    {
        canvasContext.fillStyle = color;
        canvasContext.fillRect(leftX, topY, width, height);
    } 
    function drawCircle(leftX,topY,radius,color)
    {
        canvasContext.fillStyle = color;
        canvasContext.beginPath();
        canvasContext.arc(leftX,topY,radius,0,Math.PI*2,true);
        canvasContext.fill()
    }```

【问题讨论】:

    标签: javascript collision-detection game-development


    【解决方案1】:

    使用勾股定理求两个物体的距离,然后对于圆计算半径加上您可能需要的任何额外缓冲区。

    类似

    if (distance < objects.radius + other.objects.radius) {
      return true
    }
    

    这是你的代码

    let canvas = document.getElementById("canvas");
    let movespeedX = 2;
    let movespeedY = 0;
    var canvasContext = canvas.getContext("2d");
    canvas.width = innerWidth;
    canvas.height = innerHeight;
    //newest cord
    let locationX = 20;
    let locationY = 20;
    //cords up to snakelength
    let cords = [{ X: 5, Y: 5 }];
    
    let snakeLength = 5;
    
    //food location
    let foodX;
    let foodY;
    let isfood = false;
    
    //onload draw, move and set food
    window.onload = function () {
      setInterval((callField) => {
        draw();
        move();
        food();
      }, 1000 / 60);
    
      //keyboard controls
      document.addEventListener("keydown", (event) => {
        const key = event.key.toLowerCase();
        if (key == "w" || key == "arrowup") {
          movespeedX = 0;
          movespeedY = -2;
        }
        if (key == "s" || key == "arrowdown") {
          movespeedX = 0;
          movespeedY = 2;
        }
        if (key == "a" || key == "arrowleft") {
          movespeedY = 0;
          movespeedX = -2;
        }
        if (key == "d" || key == "arrowright") {
          movespeedY = 0;
          movespeedX = 2;
        }
      });
    };
    
    function move() {
      //add movespeed to location to move all directions
      locationX += movespeedX;
      locationY += movespeedY;
    
      //if a wall is hit restart
      if (
        cords[0].X >= canvas.width ||
        cords[0].X <= 0 ||
        cords[0].Y >= canvas.height ||
        cords[0].Y < 0
      ) {
        restart();
      }
    
      //if food is hit with 20px margin (this is currently verry trippy and does not work)
      let dx = foodX - cords[0].X;
      let dy = foodY - cords[0].Y;
      let dist = Math.hypot(dx, dy);
      if (dist < 60) {
        isfood = false;
        snakeLength += 5;
      }
    
      //update cords array with newest location
      cords.unshift({ X: locationX, Y: locationY });
      if (cords.length > snakeLength) {
        delete cords[snakeLength];
      }
    }
    
    function draw() {
      //draw canvas
      drawRect(0, 0, canvas.width, canvas.height, "black");
      //draw food
      drawCircle(foodX, foodY, 20, "red");
      //draw snake
      cords.forEach((element) => {
        drawCircle(element.X + 20, element.Y, 20, "white");
      });
    }
    
    //reset to standard values
    function restart() {
      locationX = 20;
      locationY = 20;
      movespeedX = 0;
      movespeedY = 0;
      snakeLength = 1;
      cords = [{ X: 0, Y: 0 }];
    }
    
    //if the is no food, generate new cords and set food to true
    function food() {
      if (isfood === false) {
        foodX = Math.floor(Math.random() * canvas.width) + 50;
        foodY = Math.floor(Math.random() * canvas.height) + 50;
        isfood = true;
      }
    }
    
    function drawRect(leftX, topY, width, height, color) {
      canvasContext.fillStyle = color;
      canvasContext.fillRect(leftX, topY, width, height);
    }
    function drawCircle(leftX, topY, radius, color) {
      canvasContext.fillStyle = color;
      canvasContext.beginPath();
      canvasContext.arc(leftX, topY, radius, 0, Math.PI * 2, true);
      canvasContext.fill();
    }
    &lt;canvas id="canvas"&gt;&lt;/canvas&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 2019-04-30
      • 1970-01-01
      相关资源
      最近更新 更多