Перемещение объекта из точки a в b (в 2D), который может двигаться только вперед и вращаться сам - PullRequest
0 голосов
/ 21 октября 2011

Итак, у меня есть корабль, у которого внизу есть двигатели, и они могут использовать их только для продвижения вперед. Он также может вращаться вокруг своего центра. Его двигатели дают ему ускорение, поэтому он не движется с постоянной скоростью. Что я хочу сделать, так это сказать «переместиться в точку 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
}

1 Ответ

2 голосов
/ 22 октября 2011

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

Предполагая, что корабль находится в состоянии покоя при старте, просто поверните его к своей целевой точке (пока он еще в покое).Теперь ваш корабль может достичь цели, ускоряясь на 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. Начните вращаться в направлении отрицательного направления вектора перпендикуляра.Если вы уже отводите взгляд от него (не совсем наоборот, а просто отводите взгляд), то также ведите подруливающее устройство.

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


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

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

...