2011-10-21 4 views
0

Итак, у меня есть корабль с двигателем внизу и который может использовать их только для перемещения вперед. Он также может вращаться вокруг своего центра. Его подруливающие устройства дают ускорение, поэтому он не движется с постоянной скоростью. Я хочу сказать, что это «переместиться в точку B».Перемещение объекта из точки a в b (в 2D), который может двигаться только вперед и вращаться.

У меня есть решение, но оно не работает очень хорошо, и оно не вращается плавно, оно двигается рывком, и оно не заканчивается именно там, где оно должно быть, поэтому мне нужно иметь большой погрешность.

Это обычная проблема, и если да, то есть «стандартный» способ сделать это? Это легкая проблема? Я хочу, чтобы это выглядело так, будто корабль руля себя к этому моменту, используя ограничения (движители, вращение) игрока. Это исключает возможность просто отрывать его от точки А до Б. Или это так?

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

Vector diff = vector_sub(to_point, pos); 
float angle = vector_getangle(diff); 
float current_angle = vector_getangle(dir); 
float angle_diff = rightrange(angle) - rightrange(current_angle); 
float len = vector_getlength(diff); 

// "Margin of error" 
float margin = 15.0; 

// Adjust direction, only if we're not stopping the next thing we do (len <= margin) 
if (len > margin && fabs(angle_diff) > 2.0) 
{ 
    dir = vector_setangle(dir, current_angle + (angle_diff)*delta*(MY_PI) - MY_PI/2); 
} 
else if (len > margin) 
{ 
    dir = vector_normalize(diff); 
} 

// accelerate ship (if needed) 
acc.x = acc.y = speed; 
acc = vector_setangle(acc, vector_getangle(dir)); 

if (len <= margin) 
{ 
    // Player is within margin of error 
} 
+0

Существуют ли какие-либо ограничения на возможность вращения судна? Например, может ли он вращаться на 180 градусов за один тик? Или вы применяете максимальное угловое ускорение? – Kevin

+0

Корабль ограничен 360 градусами в секунду, если это то, что вы имели в виду? – ErikPerik

+0

«Рулевое управление до точки»? Вы имеете в виду, что он должен менять направление только в движении? Или он может вращаться на месте, а затем тянуть? – Beta

ответ

2

Если вы не ищете очень общее решение, которое работает в Интернете, то есть простое решение. То, что я имею в виду в режиме онлайн, постоянно пересчитывает действия по всей траектории.

Предполагая, что корабль находится в состоянии покоя, просто поверните его к своей целевой точке (пока все еще в покое). Теперь ваш корабль может достичь цели, ускоряясь за t секунд, поворачиваясь назад во время движения (в течение 0,5 секунды в соответствии с вашим ограничением) и замедляя еще на t секунд. Если расстояние между текущей точкой и назначением является d, то уравнение вам нужно решить это:

d = 0.5*a*t^2 + 0.5*a*t + 0.5*a*t^2 

Первый член пройденное расстояние, а ускорение. Второй термин - расстояние, пройденное во время вращения (v*t_rot, v=a*t, t_rot=0.5). Конечным термином является пройденное расстояние при замедлении. Решите выше для t, и у вас есть траектория.

Если корабль движется в начале, я бы сначала остановил его (просто поверните в противоположном направлении от его вектора скорости и остановитесь до упора). Теперь мы знаем, как добраться до места назначения.

Проблема с автономным вычислением траектории заключается в том, что она не очень точная. Существует хороший шанс, что вы окажетесь в непосредственной близости от цели, но не совсем на вершине.

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

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

  1. Вычислить вектор, направленный от судна к месту назначения.
  2. Разделите свой вектор текущей скорости на два компонента: по направлению к цели и перпендикулярно к нему.
  3. Если перпендикулярная скорость равна нулю, пропустите 4
  4. Начать вращение в направлении отрицательного направления перпендикулярного вектора. Если уже отворачиваться от него (не совсем наоборот, а просто смотря в сторону), то также подавать основной двигатель.

Это немного колеблется, я подозреваю, что он также стабилизируется через некоторое время. Должен признаться, я не знаю, как бы я остановился в пункте назначения.


И последний подход заключается в моделировании динамики корабля и попытка линеаризации его. Это будет нелинейная система, поэтому потребуется второй шаг. Затем преобразуйте модель в дискретную систему времени. И, наконец, примените правило управления, чтобы оно достигло целевой точки. Для этого вы можете изменить свое пространство состояния от положения и скорости до ошибки в позиции и (возможно) ошибки в скорости и, наконец, добавить регулятор управления (контур управления, который принимает текущее состояние, и генерирует вход, так что состояние переменные будут приближаться к нулю).

Это последнее довольно сложно в отсеке для математики, и вам, вероятно, потребуется немного изучить технику управления. Тем не менее, вы получите гораздо лучшие результаты, чем приведенный выше упрощенный алгоритм, который, по общему признанию, может даже не работать. Кроме того, теперь вы можете применить к нему различные правила оптимизации: свести к минимуму время достижения цели, свести к минимуму расход топлива, свести к минимуму пройденное расстояние и т. Д.

Смежные вопросы