2010-04-20 117 views
22

我目前正在爲Android開發一個簡單的2D遊戲。我有一個位於屏幕中心的靜止物體,我試圖讓該物體旋轉並指向用戶觸摸屏幕上的區域。我具有表示屏幕中心的常量座標,並且我可以獲取用戶點擊的座標。我使用的是在這個論壇中列出的公式:How to get angle between two points?計算由兩點定義的線之間的角度

  • 它說如下:「如果你想通過這兩點,橫軸定義的線之間的角度:

    double angle = atan2(y2 - y1, x2 - x1) * 180/PI;". 
    
  • 我實現了這一點,但我認爲我在屏幕座標系中工作的事實導致了錯誤計算,因爲Y座標是相反的,我不確定這是否是正確的方法,任何其他想法或建議表示讚賞。

+6

技術上你不能得到兩個*點*之間的角度。雖然你可以得到兩個*向量*之間的角度。 – ChrisF 2010-04-20 16:13:23

+6

很確定他的意思是「兩點之間畫出的線條與水平軸線之間的角度」 – 2010-04-20 16:23:03

+0

對不起,讓我改述我的標題,如何獲得由這兩點定義的線與水平線之間的角度通過我的對象在屏幕中心切入? – kingrichard2005 2010-04-20 16:24:29

回答

42

假設:x是橫軸,從左向右移動時增加。 y是垂直軸,從下到上增加。 (touch_x, touch_y)是用戶選擇的 點。 (center_x, center_y)是 屏幕中心的點。從+x軸逆時針測量theta。然後:

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所說, 採取「兩點之間的角度」的想法並沒有很好的定義。

+0

感謝Jim,無論我使用笛卡爾座標還是極座標,我如何知道計算出的角度是否基於貫穿我的對象的水平線而不是屏幕頂部的水平線,原點在左上角? – kingrichard2005 2010-04-20 16:50:43

+0

@ kingrichard2005:由於delta_x和delta_y是相對於中心點(您的對象的位置)計算得出的,所以也將針對相同的點計算出。 – 2010-04-20 17:05:00

26

有需要類似的功能我自己,這麼多頭髮拉後,我與功能提出了以下

/** 
* 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); 
} 
1

「的原點在左上角的屏幕和Y座標的增加會而X座標像正常一樣向右增加,我猜我的問題是,在應用上述公式之前,我是否必須將屏幕座標轉換爲笛卡爾座標?「

如果您使用笛卡爾座標計算角度,並且兩個點位於第1象限(其中x> 0且y> 0),則情況將與屏幕像素座標相同(除了倒置Y如果你否定Y使它正確地朝上,它將成爲象限4 ...)。將屏幕像素座標轉換爲笛卡兒並不會真正改變角度。

7

這裏有幾個答案試圖解釋「屏幕」問題,其中top left0,0bottom right是(正數)screen width, screen height。大多數電網的Y軸爲X以上不低於。

以下方法將使用屏幕值而不是「網格」值。與例外的答案唯一的區別是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; 
} 
相關問題