Спрайт эллиптическое движение - PullRequest
3 голосов
/ 27 января 2011

Я пытаюсь заставить двухмерный спрайт двигаться по «дуге» (полуэллипсу) вместо прямой линии.У меня есть начальная и конечная позиции X и Y, а также желаемый радиус.

Как лучше всего это реализовать?

Ответы [ 4 ]

0 голосов
/ 27 января 2011

Я полагаю, вы ищете кривые Безье, отметьте http://www.math.ucla.edu/~baker/java/hoefer/Bezier.htm. Источник также доступен по той же ссылке.

Если вы используете SWT, вы можете проверить http://help.eclipse.org/helios/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html#drawArc(int, int, int, int, int, int)

0 голосов
/ 27 января 2011

Возможно, вы захотите использовать параметрическую форму эллипса, формула показана здесь

http://en.wikipedia.org/wiki/Ellipse#General_parametric_form

так как у вас есть начальный pt и конечный pt, вам нужно решить для t на обоих концах,

затем шаг от начала до конца в t, с небольшими приращениями.

0 голосов
/ 27 января 2011

Я думаю, что эту проблему лучше всего решить с помощью серии преобразований координат. Для простоты обозначений предположим, что у вас есть две точки: u и v.

Предположим, что вы работаете в действительно простом случае - точки u и v находятся в точках (1, 0) и (-1, 0), соответственно, а длина большой оси в эллипсе равна 1. Тогда вы просто прослеживаете полукруг. Предполагая, что вы хотите интерполировать между точками с постоянной скоростью, вы можете использовать эту формулу:

x(t) = cos(pi * t)
y(t) = sin(pi * t)

Конечно, вам не обязательно повезло, что вы находитесь в этой настройке, и поэтому мы можем выполнить серию преобразований координат, чтобы привести вас в эту конфигурацию. Для начала давайте определим точку w как точку на полпути между u = (x0, y0) и v = (x1, y1). То есть:

w = (x2, y2) = ((x0 + x1) / 2, (y0 + y1) / 2)

Теперь предположим, что вы перевели u и v так, что w находится в начале координат. Это означает, что u и v равноудалены от начала координат вдоль противоположных векторов. Если мы используем матрицы и однородные координаты, то вы можете представить это как

     | 1  0 -x2 |
 T = | 0  1 -y2 |
     | 0  0   1 |

Позиции u и v после этого перевода задаются Tu и Tv. Давайте назовем эти точки u 'и v'. Они даны

u' = (x0 - x2, x1 - y2) = (x0 / 2 - x1 / 2, y0 / 2 - y1 / 2)
v' = (x1 - x2, y1 - y2) = (x1 / 2 - x0 / 2, y1 / 2 - y0 / 2)

Теперь мы ближе к решению исходной задачи, но у нас есть проблема, заключающаяся в том, что u 'и v' не очень хорошо выровнены по оси x, как это было в исходной задаче. Чтобы исправить это, мы применим преобразование вращения так, что u 'заканчивается в (1, 0), а v' заканчивается в (0, 1). Чтобы сделать это, мы хотим установить систему координат, в которой один из базовых векторов находится в направлении u ', а другой - в направлении, перпендикулярном к нему. Для этого мы выберем наши единичные векторы следующим образом:

e0 = u' / ||u||
e1 = perp(e0)

Где perp - некоторый единичный вектор, перпендикулярный e0. Один из способов получить это - сказать, что если e0 = (x3, y3), то e1 = perp(e0) = (-y3, x3). Вы можете проверить, что этот вектор перпендикулярен (x3, y3), так как их скалярное произведение равно нулю.

Учитывая эти векторы, мы можем определить преобразование, которое будет отображать (1, 0) в e0 и (0, 1) в e1 на

|x3 -y3  0|
|y3  x3  0|
| 0   0  1|

(последний столбец для однородной системы координат)

Конечно, это противоположность того, что мы хотим - мы пытаемся отобразить с e0 на (1, 0) и с e1 на (0, 1). Чтобы получить эту матрицу, мы просто инвертируем вышеуказанную матрицу. К счастью, поскольку мы выбрали e0 и e1 как ортонормированные, вышеуказанная матрица является ортогональной, поэтому ее обратная сторона является транспонированной:

    | x3 y3 0|
R = |-y3 x3 0|
    |  0  0 1|

Теперь, если мы применим R к u' и v', мы получим векторы (1, 0) и (-1, 0), что мы и хотим, чтобы они были. Проблема в том, что эллипс, который мы хотим отследить, не обязательно имеет высоту блока. Например, если мы назовем его высоту h, то мы будем отслеживать эллиптический путь с большой полуосью h и полуминорной осью 1. Но это легко исправить с помощью другого преобразования координат, на этот раз масштабируя высоту системы кородината с коэффициентом 1 / h, так что высота эллипса, который мы хотим отследить, равна 1. Это можно сделать с помощью следующей матрицы масштабирования:

    | 1  0  0 |
S = | 0 1/h 0 |
    | 0  0  1 |

Причина, по которой эта установка полезна, состоит в том, что мы знаем, что если мы возьмем любую точку на желаемом эллипсе между u и v, а затем применим к ней матрицу SRT, то мы в итоге преобразуем ее использовать соответствующую точку на единичной окружности, которая является путем от (1, 0) до (-1, 0). Что еще более важно, тем не менее, это работает наоборот. Если мы применим обратное из SRT к любой точке на круге единицы, мы в конечном итоге получим соответствующую точку на исходном эллиптическом пути между u и v! Чтобы заключить сделку, мы знаем, как найти точки на пути от (1, 0) до (-1, 0), и поэтому у нас есть алгоритм для решения этой проблемы:

  1. В течение заданного времени t найдите точку, в которой вы бы находились на круге юнита, если бы вы двигались от (1, 0) к (-1, 0) в момент времени t. Назовите это p.
  2. Вычислить p '= (SRT) -1 p.
  3. p' - это точка, которую вы ищете.

Вопрос в том, что такое (СТО) -1 . К счастью, у нас есть (SRT) -1 = T -1 R -1 S -1 и все эти матрицы может быть легко вычислено:

     | 1  0 -x2 |          | 1  0  x2 |
 T = | 0  1 -y2 |   T^-1 = | 0  1  y2 |
     | 0  0   1 |          | 0  0   1 |

     | x3  y3  0|          | x3 -y3 0 |
 R = |-y3  x3  0|   R^-1 = | y3  x3 0 |
     |  0   0  1|          |  0   0 1 |

     | 1  0   0 |          | 1  0   0 |
 S = | 0 1/h  0 |   S^-1 = | 0  h   0 |
     | 0  0   1 |          | 0  0   1 |

Короче говоря, окончательный алгоритм выглядит следующим образом:

  1. Учитывая u = (x0, y0) и v = (x1, y1), пусть w = (x2, y2) = ((x0 + x1) / 2, (y0 + y1) / 2).
  2. Пусть u '= u / || u || = (x3, y3).
  3. В момент времени t (для 0 & le; t & le; 1) пусть p = (cos (& pi; t), sin (& pi; t))
  4. Вычислить p '= S -1 p = (cos (& pi; t), h sin (& pi; t))
  5. Вычислить p '' = R -1 p '= (x3 cos (& pi; t) - y3 sin (& pi; t), y3 cos (& pi; t) + x3 sin (& pi; т))
  6. Вычислить p '' '= T -1 p' '= (x3 cos (& pi; t) - y3 sin (& pi; t) + x2, y3 cos (& pi; t) + x3 грех (& pi; t) + y2)
  7. Выведите p '' 'в качестве вашей точки.

Извините, если это много математики, но ваш ответ должен (надеюсь!) Дать вышеописанную процедуру.

0 голосов
/ 27 января 2011

Если вы хотите, чтобы он двигался по эллипсу, самый простой способ, который я знаю, это дать значения y как функцию времени с грехом, а значения x как функцию времени с cos.Предполагая, что вы используете System.currentTimeMillis ();, вы сохраните начальное время в переменной (например, double startTime = System.currentTimeMillis ()), а затем в каждом кадре вы получите истекшее время, вычитая текущее время извремя начала(например, elapsedTme = System.currentTimeMillis () - startTime).Тогда значение y будет (радиус в направлении y) * sin (elapsedTime * speed) + значение y центра вашего эллипса, а значение x будет (радиус в направлении x) * cos (elapsedTime * speed)+ х значение в центре вашего эллипса.

РЕДАКТИРОВАТЬ: Если у вас есть начальные координаты X и Y, но нет центра эллипса, то я думаю, что самый простой способ получить центр, это слишком выяснить остальные переменные, а затем подключить ихв уравнение.Математика не должна быть слишком сложной там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...