2010-04-20 25 views
22

Actualmente estoy desarrollando un sencillo juego 2D para Android. Tengo un objeto estacionario que está situado en el centro de la pantalla y estoy tratando de hacer girar ese objeto y señalar el área de la pantalla que toca el usuario. Tengo las coordenadas constantes que representan el centro de la pantalla y puedo obtener las coordenadas del punto que toca el usuario. Estoy usando la fórmula que se indica en este foro: How to get angle between two points?Cálculo del ángulo entre la línea definida por dos puntos

  • Se dice de la siguiente manera: "Si desea que el ángulo entre la línea definida por estos dos puntos y el eje horizontal:

    double angle = atan2(y2 - y1, x2 - x1) * 180/PI;". 
    
  • Implementé esto, pero creo que el hecho de que estoy trabajando en coordenadas de pantalla está causando un error de cálculo, ya que la coordenada Y se invierte. No estoy seguro de si esta es la manera correcta de hacerlo, cualquier otro pensamiento o sugerencias son apreciadas.

+6

Técnicamente no se puede obtener el ángulo entre dos * puntos *. Sin embargo, puedes obtener el ángulo entre dos * vectores *. – ChrisF

+6

Bastante seguro que significa "el ángulo entre una línea trazada entre dos puntos, y el eje horizontal" –

+0

Lo siento, permítanme reformular mi título, ¿cómo puedo obtener el ángulo entre la línea definida por estos dos puntos y la horizontal acceso que corta a través de mi objeto en el centro de la pantalla ?? – kingrichard2005

Respuesta

42

Suposiciones: x es el eje horizontal, y aumenta cuando se mueve de izquierda a derecha. y es el eje vertical, y aumenta de abajo hacia arriba. (touch_x, touch_y) es el punto seleccionado por el usuario. (center_x, center_y) es el punto en el centro de la pantalla . theta se mide en sentido antihorario desde el eje +x. Entonces:

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

Editar: usted ha mencionado en un comentario que los aumentos Y de arriba a abajo. En ese caso ,

delta_y = center_y - touch_y 

Sin embargo, sería más correcto para describir esto como expresando (touch_x, touch_y) en coordenadas polares con respecto a (center_x, center_y). Como ChrisF mencionó, , la idea de tomar un "ángulo entre dos puntos" no está bien definida.

+0

Gracias Jim, si estoy usando coordenadas cartesianas o polares, ¿cómo sabría si el ángulo calculado se basa en la línea horizontal que atraviesa mi objeto y no en la horizontal en la parte superior de la pantalla, que está saliendo de la origen en la parte superior izquierda? – kingrichard2005

+0

@ kingrichard2005: Dado que delta_x y delta_y se calculan con respecto al punto central (la ubicación de su objeto), theta también se calculará con respecto al mismo punto. –

26

Tenía una necesidad de una funcionalidad similar a mí mismo, por lo que después de tirar de la cantidad de pelo que se me ocurrió la función de abajo

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

"El origen está en la parte superior izquierda de la pantalla y la coordenada y aumenta ir hacia abajo, mientras que el X-Coordinate aumenta a la derecha como normal. Supongo que mi pregunta se convierte, ¿tengo que convertir las coordenadas de la pantalla en coordenadas cartesianas antes de aplicar la fórmula anterior? "

Si estaba calculando el ángulo usando coordenadas cartesianas, y ambos puntos estaban en el cuadrante 1 (donde x> 0 ey> 0), la situación sería idéntica a las coordenadas de píxeles de la pantalla (excepto la Y invertida Si niegas a Y para ponerlo boca arriba, se convierte en el cuadrante 4 ...). La conversión de las coordenadas del píxel de la pantalla al cartesiano realmente no cambia el ángulo.

7

Algunas respuestas aquí han tratado de explicar el tema "pantalla", donde es top left0,0 y bottom right es (positivo) screen width, screen height. La mayoría de las cuadrículas tienen el eje Y como positivo por encima de X no inferior.

El siguiente método funcionará con valores de pantalla en lugar de valores de "cuadrícula". La única diferencia con la respuesta exceptuada es que los valores Y están invertidos.

/** 
* 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; 
} 
Cuestiones relacionadas