以360度为单位获取角度

10

我想在我的游戏中获得以360度为单位的角度... 我需要知道玩家朝向哪个方向...

图片描述

这段代码可以获取正确的角度,但只能以90度为增量:(也就是说,当我点击上左象限时,我会得到0到90度的角度...下左为0到-90度,等等...)

图片描述

    var dY = this.pos.y-e.gameY;            //opposite
    var dX = this.pos.x-e.gameX;            //adjacent
    var dist = Math.sqrt((dY*dY)+(dX*dX));  //hypotenuse
    var sin = dY/dist;                      //opposite over hypotenuse
    var radians = Math.asin(sin);
    var degrees = radians*(180/Math.PI);    //convert from radians to degrees
    this.calculatedAngle = degrees;     

如何以360度的方式表示?


这是另一个例子:前两个图示问题...当我在左下象限点击时,它会从x轴绘制出一个直角三角形...

我需要它像后面两幅图一样,不断绘制角度:

图片描述


你有任何数据可以用来展示你在所有四个象限中的计算吗? - Xotic750
你可以使用 dydx 的符号来区分象限,根据需要为你的结果添加偏移量。 - orange
@Xotic750 你是什么意思?我只是获取用户点击的地图上的点 (e.gameX 或 e.gameY),并获取到玩家当前位置的距离。Orange,我也不太明白你的意思。 - user3871
你的图表原点是在 (0, 0) 吗?所有数值都是相对于该原点的吗?因此,玩家和点击的示例可能是 (1, 1),(-1, 1),(-1, -1) 和 (1, -1)。也就是说,玩家可能在 (1, 1) 处并在 (2, 2) 处获得点击,或者玩家始终在 (0, 0) 而点击在其他地方吗? - Xotic750
@Xotic750,它们并不是。它们只是玩家与屏幕上点击点之间的坐标。因此,玩家可能在(200,300)处,点击(400,500),distX = 200,distY = 200。 - user3871
3个回答

14

您可以直接使用atan2函数从坐标中获取角度,而无需计算额外的信息,如斜边长度。这个函数是在FORTRAN早期为了像您这样的情况而设计的。

请注意以下两点:

  1. atan2函数已经被创建来自动处理许多可能的情况,但除了一种情况以外都可以处理。
  2. 它将输出一个范围为 (-PI, PI] 的值。

当两个坐标都是(0, 0)时,未定义角度(向量的大小为零时所有角度等效),所以我将该角度任意设置为0度。为了获得所需的范围,需要一些简单的逻辑和加法运算。

var Vx = this.pos.x - e.gameX;
var Vy = this.pos.y - e.gameY;

var radians;

if (Vx || Vy) {
    radians = Math.atan2(Vy, Vx);
} else {
    radians = 0;
}

if (radians < 0) {
    radians += 2*Math.PI;
}

var degrees = radians * 180 / Math.PI;

this.calculatedAngle = degrees;

结果将是一个角度,适用于所有情况并在所需范围内 [0,360°)。

示例


function showDegrees(e, svg) {
 var rectangle = svg.getBoundingClientRect();
 var targetX = (rectangle.left + rectangle.right)/2;
 var targetY = (rectangle.top + rectangle.bottom)/2;
 var Vx = Math.round(e.clientX - targetX);
 var Vy = Math.round(targetY - e.clientY);
 var radians = Math.atan2(Vy, Vx);
 if (radians < 0) radians += 2*Math.PI;
 var degrees = Math.round(radians*180/Math.PI);
 var textBox = document.getElementById('showdegrees');
 textBox.innerHTML = degrees + '&deg;' + ' (' + Vx + ', ' + Vy + ')';
 textBox.setAttribute('x', Math.round(100 + Vx));
 textBox.setAttribute('y', Math.round(100 - Vy));
}
<svg width="200" height="200" viewBox="0 0 200 200" onmousemove="showDegrees(evt, this)">
<text x="0" y="0" fill="red" style="font-size: 12px"  id="showdegrees">Info</text>
<line x1="100" y1="0" x2="100" y2="200" style="stroke: black; stroke-width: 1" />
<line x1="0" y1="100" x2="200" y2="100" style="stroke: black; stroke-width: 1" />
</svg>


5

试试这个:

var dY = this.pos.y - e.gameY,          // opposite
    dX = this.pos.x - e.gameX,          // adjacent
    radians = Math.atan(dY/dX);         // wrong, in [-1/2 pi, 1/2 pi]
if(1/dX < 0) radians += Math.PI;        // fixed, in [-1/2 pi, 3/2 pi]
if(1/radians < 0) radians += 2*Math.PI; // fixed, in [+0, 2 pi]
var degrees = radians*180/Math.PI;      // from radians to degrees

解释:

  • 使用Math.atan和正切更好地计算弧度。使用Math.sqrt计算斜边是昂贵的。
  • Math.atan给出介于-1/2 pi1/2 pi之间的角度,即右半圆。要修正它,只需在dX为负时加上pi
  • 然后我们得到介于-1/2 pi3/2 pi之间的角度。因此,如果它为负数,我们会加上2pi以获得介于02pi之间的角度。
  • 请注意,我们必须考虑-0为负,以使其正常工作。因此,我们检查它们的倒数,而不是检查dX < 0radians < 0
  • 请注意,如果dXdY都为0(或-0),则最终结果将为NaN

2
您需要使用比arcsin更多的信息来解决这个问题。原因是,如您所知,arcsin仅返回介于-π/2和π/2(-90度和90度)之间的值。
因此,要找出另一部分,您需要知道自己处于哪个象限。
在第二象限中,arcsin介于90和0之间,实际角度介于90和180之间。因此,如果您处于第二象限,则180-计算出的角度=实际角度(180-90 = 90,180-0 = 180)
在第三象限中,arcsin介于0和-90之间。实际角度介于180和270之间。因此,再次,180-计算出的角度=实际角度(180-0=180, 180-(-90)=270)
在第四象限中,arcsin介于-90和0之间。实际角度介于270和360之间。因此,360+计算出的角度=实际角度(360+(-90)=270, 360+0)=360)
对于第一象限也是同样的道理,您只需要不进行转换即可。(0+360=360(等同于0),90+360=450(等同于90))。
因此,首先确定所处的象限,并根据该规则进行计算。对于(x,y)坐标,如果x为正且y为正,则您位于第一象限。如果x为负且y为正,则您位于第二象限。如果x为负且y为负,则您位于第三象限。如果x为正且y为负,则您位于第四象限。
因此,在您的情况下,距离原点的距离是您的(dX,dY)坐标对,因此应该这样做:
//your original code...
var degrees = radians*(180/Math.PI);    //convert from radians to degrees

//then


if (dX>=0 and dY>=0)
{//quadrant 1
//no transformation, do nothing
}
if (dX>=0 and dy<0) 
{ //quadrant 4
degrees=360+degrees;
}
if (dX<0 and dy<0) 
{ //quadrant 3
degrees=180-degrees;
}
if (dX<0 and dy>0) 
{ //quadrant 2
degrees=180-degrees;
}


this.calculatedAngle = degrees;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接