我目前正在为Android开发一款简单的2D游戏。我有一个静止的物体位于屏幕的中心,我试图让该物体旋转并指向屏幕上用户接触的区域。我有恒定的坐标代表屏幕的中心,我可以得到用户点击的点的坐标。我正在使用此论坛中概述的公式:How to get angle between two points?
如下所示“如果你想要这两个点定义的直线与水平轴之间的角度:
double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;".
我实现了这一点,但我认为我在屏幕坐标中工作的事实导致错误计算,因为Y坐标是反转的。我不确定这是否是正确的方法,任何其他想法或建议都表示赞赏。
答案 0 :(得分:57)
假设:x
是水平轴,从左向右移动时增加。
y
是垂直轴,从下到上增加。 (touch_x, touch_y)
是
用户选择的点。 (center_x, center_y)
是该中心的重点
屏幕。从theta
轴逆时针测量+x
。然后:
delta_x = touch_x - center_x
delta_y = touch_y - center_y
theta_radians = atan2(delta_y, delta_x)
修改:您在评论中提到y从上到下增加。在那里面 案例,
delta_y = center_y - touch_y
但将此描述为表达(touch_x, touch_y)
更为正确
在相对于(center_x, center_y)
的极坐标中。正如ChrisF所说,
采取“两点之间的角度”的想法尚未明确界定。
答案 1 :(得分:29)
我自己需要类似的功能,所以经过多次拔毛我想出了下面的功能
/**
* Fetches angle relative to screen centre point
* where 3 O'Clock is 0 and 12 O'Clock is 270 degrees
*
* @param screenPoint
* @return angle in degress from 0-360.
*/
public double getAngle(Point screenPoint) {
double dx = screenPoint.getX() - mCentreX;
// Minus to correct for coord re-mapping
double dy = -(screenPoint.getY() - mCentreY);
double inRads = Math.atan2(dy, dx);
// We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12 O'clock
if (inRads < 0)
inRads = Math.abs(inRads);
else
inRads = 2 * Math.PI - inRads;
return Math.toDegrees(inRads);
}
答案 2 :(得分:15)
这里的一些答案试图解释&#34;屏幕&#34; top left
为0,0
且bottom right
为(正)screen width, screen height
的问题。大多数网格的Y
轴都高于X
以下的正值。
以下方法适用于屏幕值,而不是&#34; grid&#34;值。与例外答案的唯一区别是Y
值被反转。
/**
* Work out the angle from the x horizontal winding anti-clockwise
* in screen space.
*
* The value returned from the following should be 315.
* <pre>
* x,y -------------
* | 1,1
* | \
* | \
* | 2,2
* </pre>
* @param p1
* @param p2
* @return - a double from 0 to 360
*/
public static double angleOf(PointF p1, PointF p2) {
// NOTE: Remember that most math has the Y axis as positive above the X.
// However, for screens we have Y as positive below. For this reason,
// the Y values are inverted to get the expected results.
final double deltaY = (p1.y - p2.y);
final double deltaX = (p2.x - p1.x);
final double result = Math.toDegrees(Math.atan2(deltaY, deltaX));
return (result < 0) ? (360d + result) : result;
}
答案 3 :(得分:1)
“原点位于屏幕的左上角,Y坐标增加下降,而X坐标则正常增加。我想我的问题变成了,我是否需要转换屏幕坐标在应用上述公式之前的笛卡尔坐标?“
如果使用笛卡尔坐标计算角度,并且两个点都在象限1(其中x> 0且y> 0),则情况与屏幕像素坐标相同(除了颠倒的Y事物)如果你否定Y以使其正确向上,它就会成为象限4 ...)。将屏幕像素坐标转换为笛卡尔并不会真正改变角度。
答案 4 :(得分:0)
使用pygame:
dy = p1.y - p2.y
dX = p2.x - p1.x
rads = atan2(dy,dx)
degs = degrees(rads)
if degs < 0 :
degs +=90
对我有用
答案 5 :(得分:0)
在android中,我使用Kotlin做到了这一点:
override func willMove(toParent parent: UIViewController?) {
navigationController?.navigationBar.prefersLargeTitles = true
}
答案 6 :(得分:0)
fun calculateAngle(
touchX: Float,
touchY: Float,
centerX: Float,
centerY: Float
): Float {
val deltaX = centerX - touchX
val deltaY = centerY - touchY
return Math.toDegrees(atan2(deltaY.toDouble(), deltaX.toDouble())).toFloat()
}
这个函数会返回类似的值
如果我们+ 180
到返回值,那么我们将从从右到左获取值,就像
360(<=> 0) -> 45 -> 90 -> 135 -> 180 -> 225 -> 270 -> 315
类似于我们drawArc
时的角度