【问题标题】:Javascript Enemy angle/directionJavascript敌人角度/方向
【发布时间】:2018-02-02 06:47:22
【问题描述】:

我做了一个小游戏,里面有 3 个对象

玩家:可以使用 WASD 移动

子弹:被点击事件监听器移动

敌人:像僵尸一样跟随玩家。

如何使僵尸的角度与他移动的方向一致,而不是始终面向玩家对象?

Fiddle

    tick: function() {
     enemy.angle = Math.atan2(player.y - enemy.y, player.x - enemy.x);// * (180 / Math.PI);
    },

上面是我用来让敌人面对玩家的代码

【问题讨论】:

  • 僵尸总是朝着玩家移动,所以“他移动的方向”和“总是面向玩家对象”是一样的。
  • 嗯,我看不到任何敌人来了
  • 他在你身上
  • 我试图让绿色三角形面向他移动的角度,而不是始终面向玩家。
  • @Brad 但他总是向玩家移动。为了让它变得明显,他需要另一种行为,比如扫射或撤退,或者寻找掩护(注意僵尸不应该做这些事情;p)。

标签: javascript html


【解决方案1】:

我明白你想问什么,但说真的,现在僵尸总是直接冲向玩家,所以如果它以其他方式看起来会很奇怪。你需要做的是真正让僵尸慢慢转身并自行行走,而不是仅仅减少它与玩家之间的欧式距离。

第一个词干,我将为您做的是计算旋转。我们必须慢慢转动每一个刻度,而不是立即到达正确的角度:

    tick: function() {
        // 1 degree per tick
        const rotationSpeed = (1/180)*Math.PI;
        // the angle we want - facing the player
        const desiredAngle = Math.atan2(player.y - enemy.y, player.x - enemy.x)
        // transition angle will be explained below 
        enemy.angle = transitionAngle(enemy.angle, desiredAngle,rotationSpeed );
    },

这并不像听起来那么容易,因为您需要计算再次面对玩家时向左还是向右更快。幸运的是,一旦你知道你需要什么,这很容易谷歌搜索。我的功能基于this answer

function transitionAngle(fromAngle, toAngle, speed) {
    // normalize the angles to 0-360 range
    const rad360 = 2*Math.PI;
    fromAngle = fromAngle % rad360;
    toAngle = toAngle % rad360;



    if (fromAngle < toAngle) {
        if (Math.abs(fromAngle - toAngle) < Math.PI)
            fromAngle += speed;
        else fromAngle -= speed;
    }

    else {
        if (Math.abs(fromAngle - toAngle) < Math.PI)
            fromAngle -= speed;
        else fromAngle += speed;
    }
    return fromAngle;
}

这样一来,丧尸就慢了下来,看起来已经好了一点。

      var canvas = document.getElementById('canvas');
      var context = canvas.getContext('2d');
      var bounds = canvas.getBoundingClientRect();
      var mouseX = 0.0;
      var mouseY = 0.0;
      var pressingDown = false;
      var pressingUp = false;
      var pressingLeft = false;
      var pressingRight = false;

      var player = {
        x: 210,
        y: 250,
        radius: 17.5,
        angle: 0.0,
        tick: function() {
          this.angle = Math.atan2(mouseY - this.y, mouseX - this.x);
        },

        draw: function() {
          context.fillStyle = "darkred";
          context.strokeStyle = "black";
          context.translate(this.x, this.y);
          context.rotate(this.angle);
          context.beginPath();
          context.moveTo(this.radius, 0.0);
          context.lineTo(-0.5 * this.radius, 0.5 * this.radius);
          context.lineTo(-0.5 * this.radius, -0.5 * this.radius);
          context.lineTo(this.radius, 0.0);
          context.fill();
          context.stroke();
          context.rotate(-this.angle);
          context.translate(-this.x, -this.y);
        },

        updatePlayerPosition: function() {
          if (pressingRight)
            player.x += 1;
          if (pressingLeft)
            player.x -= 1;
          if (pressingDown)
            player.y += 1;
          if (pressingUp)
            player.y -= 1;
        }

      }

      var bullet = {
        x: player.x,
        y: player.y,
        dx: 0.0,
        dy: 0.0,
        radius: 5.0,

        tick: function() {
          this.x += this.dx;
          this.y += this.dy;

          if (this.x + this.radius < 0.0 || this.x - this.radius > canvas.width || this.y + this.radius < 0.0 || this.y - this.radius > canvas.height) {
            this.dx = 0.0;
            this.dy = 0.0;
          }
        },

        render: function() {
          context.fillStyle = "darkcyan";
          context.strokeStyle = "white";
          context.beginPath();
          context.arc(this.x, this.y, this.radius, 0.0, 2.0 * Math.PI, false);
          context.fill();
          context.stroke();
        }
      };
	
  	var enemy = {       
    		x: 200,
        y: 300,
        radius: 17.5,
        angle: 0.0,
        tick: function() {
            // 1 degree per tick
            const rotationSpeed = (1/180)*Math.PI;
            const desiredAngle = Math.atan2(player.y - enemy.y, player.x - enemy.x)
            enemy.angle = transitionAngle(enemy.angle, desiredAngle,rotationSpeed );
        },

        draw: function() {
          context.fillStyle = "Green";
          context.strokeStyle = "darkgreen";
          context.translate(this.x, this.y);
          context.rotate(this.angle);
          context.beginPath();
          context.moveTo(this.radius, 0.0);
          context.lineTo(-0.5 * this.radius, 0.5 * this.radius);
          context.lineTo(-0.5 * this.radius, -0.5 * this.radius);
          context.lineTo(this.radius, 0.0);
          context.fill();
          context.stroke();
          context.rotate(-this.angle);
          context.translate(-this.x, -this.y);
        },
        drawEnemy: function(something){
          var diffX = player.x - something.x;
          var diffY = player.y - something.y

        if (diffX > 0)
          something.x += .3
        else
          something.x -= .3;

        if (diffY > 0)
          something.y += .3
        else
          something.y -= .3;
      }
        
        }





      function Refresh() {
        context.clearRect(0, 0, canvas.width, canvas.height);
        bullet.render();
        bullet.tick();
        player.draw();
        player.tick();
        player.updatePlayerPosition();
        enemy.draw();
        enemy.tick();
        enemy.drawEnemy(enemy);

      }
      

      setInterval(Refresh, 0)

      window.onmousemove = function(e) {
        mouseX = e.clientX - bounds.left;
        mouseY = e.clientY - bounds.top;
      }

      document.onkeydown = function(event) {
        if (event.keyCode === 83) //s
          pressingDown = true;
        else if (event.keyCode === 87) //w
          pressingUp = true;
        else if (event.keyCode === 65) //a
          pressingLeft = true;
        else if (event.keyCode === 68) //d
          pressingRight = true;
      }

      document.onkeyup = function(event) {
        if (event.keyCode === 83) //s
          pressingDown = false;
        else if (event.keyCode === 87) //w
          pressingUp = false;
        else if (event.keyCode === 65) //a
          pressingLeft = false;
        else if (event.keyCode === 68) //d
          pressingRight = false;
      }

      window.onmousedown = function(e) {
        // The mouse pos - the player pos gives a vector
        // that points from the player toward the mouse
        var x = mouseX - player.x;
        var y = mouseY - player.y;

        // Using pythagoras' theorm to find the distance (the length of the vector)
        var l = Math.sqrt(x * x + y * y);

        // Dividing by the distance gives a normalized vector whose length is 1
        x = x / l;
        y = y / l;

        // Reset bullet position
        bullet.x = player.x;
        bullet.y = player.y;

        // Get the bullet to travel towards the mouse pos with a new speed of 10.0 (you can change this)
        bullet.dx = x * 10.0;
        bullet.dy = y * 10.0;
      }

function transitionAngle(fromAngle, toAngle, speed) {
    // normalize the angles to 0-360 range
    const rad360 = 2*Math.PI;
    fromAngle = fromAngle % rad360;
    toAngle = toAngle % rad360;
    
    
    
    if (fromAngle < toAngle) {
        if (Math.abs(fromAngle - toAngle) < Math.PI)
            fromAngle += speed;
        else fromAngle -= speed;
    }

    else {
        if (Math.abs(fromAngle - toAngle) < Math.PI)
            fromAngle -= speed;
        else fromAngle += speed;
    }
    return fromAngle;
}
&lt;canvas id="canvas" style="border:2px solid darkred" width="700" height="500"&gt;&lt;/canvas&gt;

工作的第二部分——我将把它留给你——是让僵尸真正朝着它所面对的方向行走。为此,请为其指定步行速度,然后使用僵尸角度的sincos 乘以速度来获得X 和Y 偏移量。同样,谷歌是你的朋友,只需输入“move by speed and angle javascript”。

【讨论】:

  • 在 OP 的版本中似乎有一个我没有注意到的奇怪错误:如果你沿着绿色箭头的左侧向上或向下移动,它的转动速度大约是我的两倍期待它,然后在下一次用户输入时更正其面向角度。
  • jsfiddle.net/nuc23154/20 我把它放到了我的代码中,但是我一定做错了,你能澄清一下这就是我所要做的吗?
  • @Brad 您忘记了我为您编写的函数中的第三个“速度”参数。为什么不直接复制/粘贴我为 tick 方法提供的代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多