Ответы:
Параболическая функция лотка определяется как:
Fx = Vox*t + Ox;
Fy = -0.5 * g * t * t + Voy*t + Oy;
Известные значения:
P: the target point.
O: the origin point.
g: gravity.
t: time needed to impact.
Неизвестные значения:
Vo: Initial Velocity
Чтобы вычислить «Vo», мы можем дать значения функции F:
't' = flight time 'duration'
'F' = target point 'P'
(Px-Ox)
Vox = --------
duration
Py + 0.5* g * duration * duration - Oy
Voy = ---------------------------------------
duration
Теперь вы можете получить все значения, чтобы достичь цели из источника, давая значения t в уравнение F:
When t = 0 => F == O (Origin)
When t = duration => F == P (Target)
Недавно мне пришлось решить аналогичную проблему, я нашел два решения, основанные на формуле, которую я нашел на странице википедии «Дэн Человек», уже упоминавшейся: Траектория снаряда
В этом решении вам фактически необходимо либо фиксированный угол запуска, либо скорость x. Скорость Y не нужна, поскольку мы запускаем снаряд под определенным углом.
Решение 1, угол запуска фиксирован, рассчитать скорость:
g = 9.81; // gravity
x = 49; // target x
y = 0; // target y
o = 45; // launch angle
v = (sqrt(g) * sqrt(x) * sqrt((tan(o)*tan(o))+1)) / sqrt(2 * tan(o) - (2 * g * y) / x); // velocity
Решение 2, скорость фиксирована, рассчитать угол запуска:
g = 9.81; // gravity
v = 40; // velocity
x = 42; // target x
y = 0; // target y
s = (v * v * v * v) - g * (g * (x * x) + 2 * y * (v * v)); //substitution
o = atan(((v * v) + sqrt(s)) / (g * x)); // launch angle
В моем случае это решение работало довольно хорошо.
Если вас не волнует, математически ли это правильно, только то, что это выглядит достаточно корректно, рассчитайте прямой путь и заставьте ваш снаряд следовать этому пути, но «подтолкните его вверх» вдоль нормали этой линии в зависимости от расстояния вниз отрезок линии, поэтому он поднимается по мере приближения к середине отрезка и падает по мере удаления от середины отрезка.
Вы можете использовать синусоидальную волну для этого, используя диапазон градусов от -90 до +90 (где -90 - левая точка на отрезке, 90 - правая точка, а вы - в середине), и умножить результат постоянным, чтобы увеличить его.
Если вам нужен чисто правильный математический / физический ответ, это не поможет. Если вы этого не сделаете, это может работать очень хорошо для вас!
Не забывайте, что при программировании игр используются иллюзии, которые выглядят правильными (и обходятся дешевле) вместо реализма.
Если вам просто нужно что-то правильное и с фиксированной скоростью, вы можете использовать этот очень упрощенный метод.
distance = to.x - from.x;
angleToPoint = atan2(to.y - from.y, to.x - from.x);
distanceFactor = 1/1000;
angleCorrection = (PI*0.18) * (distance * distanceFactor);
velocity.X = cos(angleToPoint+angleCorrection) * power;
velocity.Y = sin(angleToPoint+angleCorrection) * power;
Расстояние может быть отрицательным, но оно все равно будет работать, потому что угол также зависит от расстояния. Если расстояние отрицательно, угол, который нужно добавить, тоже отрицателен.
Вам нужно будет поиграться с distanceFactor, чтобы найти правильное значение. Это зависит от тяжести и мощности снаряда. Оно должно быть около 1, деленное на максимальное расстояние, которое может пройти снаряд.