2010-04-20 2 views
22

В настоящее время я разрабатываю простую 2D-игру для Android. У меня есть неподвижный объект, который находится в центре экрана, и я пытаюсь заставить этот объект вращаться и указывать на область на экране, к которой прикасается пользователь. У меня есть постоянные координаты, которые представляют центр экрана, и я могу получить координаты точки, которую пользователь нажимает. Я использую формулу, изложенную в этом форуме: How to get angle between two points?Расчет угла между строкой, определяемой двумя точками

  • Он говорит следующее: «Если вы хотите, чтобы угол между линией, определяемой этими двумя точками и горизонтальной оси:

    double angle = atan2(y2 - y1, x2 - x1) * 180/PI;". 
    
  • Я реализовал это, но я думаю, что факт, что я работаю в координатах экрана, вызывает просчет, так как координата Y обращена. Я не уверен, что это правильный путь для этого, любые другие мысли или предложения.

+6

Технически вы не можете получить угол между двумя точками *. Вы можете получить угол между двумя * векторами *. – ChrisF

+6

Довольно уверен, что он означает «угол между линией, проведенной между двумя точками, и горизонтальной осью» –

+0

Прошу прощения, позвольте мне перефразировать мой заголовок, как мне получить угол между строкой, определяемой этими двумя точками, и горизонтальной доступ, который прорезает мой объект в центре экрана? – kingrichard2005

ответ

42

Предположения: 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) 

Edit: Вы упомянули в комментарии, что у возрастает от верха до низа. В этом случае ,

delta_y = center_y - touch_y 

Но было бы правильнее описать это как выражение (touch_x, touch_y) в полярных координатах относительно (center_x, center_y). Как упоминал ChrisF, идея определения «угла между двумя точками» не определена.

+0

Спасибо Джим, независимо от того, использую ли я декартовы или полярные координаты, как узнать, рассчитан ли угол на горизонтальной линии, которая прорезает мой объект, а не горизонтальную в верхней части экрана, которая выходит из происхождение в левом верхнем? – kingrichard2005

+0

@ kingrichard2005: Поскольку delta_x и delta_y вычисляются относительно центральной точки (местоположения вашего объекта), тота также будет рассчитана по той же точке. –

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 left является 0,0 и bottom 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; 
} 
Смежные вопросы