2010-04-20 42 views
22

Tôi hiện đang phát triển trò chơi 2D đơn giản dành cho Android. Tôi có một vật thể đứng yên nằm ở giữa màn hình và tôi đang cố gắng để đối tượng đó quay và trỏ đến khu vực trên màn hình mà người dùng chạm vào. Tôi có các tọa độ không đổi đại diện cho tâm của màn hình và tôi có thể nhận tọa độ của điểm mà người dùng chạm vào. Tôi đang sử dụng công thức được nêu trong diễn đàn này: How to get angle between two points?Tính góc giữa đường được xác định bởi hai điểm

  • Nó nói như sau: "Nếu bạn muốn các góc giữa đường xác định bởi hai điểm này và trục ngang:

    double angle = atan2(y2 - y1, x2 - x1) * 180/PI;". 
    
  • Tôi đã thực hiện điều này, nhưng tôi nghĩ thực tế là tôi đang làm việc trong các tọa độ màn hình đang gây ra một tính toán sai lầm, vì tọa độ Y bị đảo ngược.Tôi không chắc liệu đây có phải là cách thích hợp để thực hiện nó hay không. hoặc đề xuất được đánh giá cao.

+6

Về mặt kỹ thuật, bạn không thể nhận được góc giữa hai điểm *. Bạn có thể nhận được góc giữa hai * vectơ * mặc dù. – ChrisF

+6

Khá chắc chắn anh ấy có nghĩa là "góc giữa một đường thẳng được vẽ giữa hai điểm và trục ngang" –

+0

Tôi xin lỗi, hãy để tôi lặp lại tiêu đề của mình, làm cách nào để có được góc giữa đường được xác định bởi hai điểm này và điểm ngang truy cập mà cắt qua đối tượng của tôi ở trung tâm của màn hình ?? – kingrichard2005

Trả lời

42

Giả định: x là trục ngang và tăng khi di chuyển từ trái sang phải. y là trục thẳng đứng và tăng từ dưới lên trên. (touch_x, touch_y) là điểm do người dùng chọn. (center_x, center_y) là điểm ở giữa màn hình . theta được đo ngược chiều kim đồng hồ từ trục +x. Sau đó:

delta_x = touch_x - center_x 
delta_y = touch_y - center_y 
theta_radians = atan2(delta_y, delta_x) 

Sửa: bạn đề cập đến trong một chú thích rằng y tăng từ trên xuống dưới. Trong đó trường hợp,

delta_y = center_y - touch_y 

Nhưng nó sẽ là chính xác hơn để mô tả điều này như thể hiện (touch_x, touch_y) ở cực phối tương đối so với (center_x, center_y). Như ChrisF đã đề cập, ý tưởng lấy một "góc giữa hai điểm" không được xác định rõ.

+0

Cảm ơn Jim, liệu tôi có đang sử dụng tọa độ Descartes hay cực hay không, làm cách nào tôi biết liệu góc được tính toán có dựa trên đường ngang cắt xuyên qua đối tượng của tôi chứ không phải nằm ngang trên đầu màn hình, sắp ra khỏi nguồn gốc ở trên cùng bên trái ?? – kingrichard2005

+0

@ kingrichard2005: Vì delta_x và delta_y được tính theo điểm trung tâm (vị trí của đối tượng của bạn), theta cũng sẽ được tính theo cùng một điểm. –

26

Đã có một nhu cầu cho chức năng tương tự bản thân mình, vì vậy sau nhiều tóc kéo tôi đến với các chức năng dưới đây

/** 
* 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

"nguồn gốc là ở phía trên cùng bên trái của màn hình và Y-Phối hợp tăng đi xuống, trong khi X-Coordinate tăng lên bên phải như bình thường. Tôi đoán câu hỏi của tôi trở thành, tôi có phải chuyển đổi tọa độ màn hình thành tọa độ Descartes trước khi áp dụng công thức trên không? "

Nếu bạn tính toán góc bằng tọa độ Descartes, và cả hai điểm ở góc phần tư 1 (trong đó x> 0 và y> 0), tình hình sẽ giống với tọa độ pixel màn hình (ngoại trừ ngược) Nếu bạn phủ nhận Y để làm cho nó ở bên phải, nó sẽ trở thành góc phần tư 4 ...). Chuyển đổi tọa độ điểm ảnh màn hình sang Cartesian không thực sự thay đổi góc.

7

Một vài câu trả lời ở đây đã cố gắng giải thích vấn đề "màn hình" trong đó top left0,0bottom right là (dương) screen width, screen height. Hầu hết các lưới có trục Y là dương trên X không thấp hơn.

Phương pháp sau sẽ hoạt động với giá trị màn hình thay vì giá trị "lưới". Sự khác biệt duy nhất với câu trả lời ngoại trừ là các giá trị Y được đảo ngược.

/** 
* 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; 
} 
Các vấn đề liên quan