我想在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轴绘制一个直角三角形......
我需要它像下面的2张图片一样,它会不断地绘制角度:
答案 0 :(得分:3)
您可以直接从坐标中执行此操作,而无需使用atan2
函数来计算斜边等额外信息,该函数是在FORTRAN早期设计的,与您的情况完全相同。
注意两件重要的事情:
atan2
函数以自动处理多个可能情况中的除之外的所有,并且(-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 + '°' + ' (' + 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>
答案 1 :(得分:2)
试试这个:
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 pi
和1/2 pi
之间的角度,即右半圈。要解决此问题,只需加pi
,以防dX
为负数。-1/2 pi
和3/2 pi
之间的角度。因此,如果它是否定的,我们总结2 pi
以获得0
和2 pi
之间的角度。-0
否定才能使其正常运行。因此,我们不会检查dX < 0
和radians < 0
,而是检查它们的反向。NaN
和dX
都是dY
(或0
),则最终结果为-0
。答案 2 :(得分:1)
你需要使用比arcsin更多的信息来解决这个问题。原因是arcsin只返回-π/ 2和π/ 2(-90度和90度)之间的值,正如您所知道的那样。
因此,要找出另一部分,您需要了解您所在的象限。
在象限2中,arcsin介于90和0之间,实际角度介于90和180之间。因此,如果您位于象限2,180 - calculated angle
= real angle
。 (180-90=90, 180-0=180)
。
在象限3中,arcsin介于0和-90之间。真实角度在180到270之间。再次,180 - calculated angle
= real angle
。 (180-0=180, 180-(-90)=270)
。
在象限4中,arcsin在-90和0之间。真实角度在270到360之间。所以360 + calculated angle
= real angle
。 (360+(-90)=270, 360+0)=360)
。
象限1也是如此,你不需要进行转换。 (0+360=360 (equivalent to 0), 90+360=450 (equivalent to 90) )
。
因此,首先确定象限,并根据该规则应用规则。 对于(x,y)坐标,如果x为正且y为正,则为象限1.如果x为负且y为正,则为象限2.如果x为负且y为负,则为象限3如果x为正且y为负,则为象限4。
所以在你的情况下,与原点的距离是(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;