Управляемая ракета с постоянным временем

9

Я строю игру с игроками и ракетами.

Я хочу запустить ракету из P1 в P2. Ракете всегда нужно ровно пять секунд, чтобы достичь Р2. Ракета должна также отслеживать P2. Если P2 отодвигается дальше, ракета должна ускориться, чтобы удовлетворить временным ограничениям. Если P2 движется влево, ракета должна двигаться влево (и также менять скорость). Если P2 приближается к P1, ракета должна замедлиться.

Это возможно? Какой лучший способ сделать это?

В настоящее время у меня нет класса Vector2D (на самом деле это не игра, но аналогия работает хорошо), поэтому, если возможно, я бы хотел решение, которое не требует его.

Изменить: Это на самом деле не ракета либо. :)

Спасибо!

Питер
источник
1
(Я немного боюсь, что кто-то спросит о наведении ракеты, квалифицируемой как «это на самом деле не игра», но…) Есть ли у вас какие-либо ограничения на форму траектории ракеты? Может ли он всегда следовать по прямой линии между своей текущей позицией и игроком 2? Есть ли у него ограничение по радиусу разворота или ускорению? Нужно ли избегать препятствий? Кроме того, вы упомянули Vector2D - можно ли предположить, что вам это нужно только в 2D? Вы можете выполнять всю векторную математику по компонентам, но писать неуклюже по сравнению с простым классом векторной математики, поэтому я не совсем понимаю предпочтение этому.
DMGregory
Вы пропустили дополнительную информацию. Есть ли ограничения? Ракеты движутся вдоль линии, или мы должны заботиться о направлениях, и сколько измерений в конечном итоге?
liggiorgio
Путь не должен быть ограничен. Единственные правила: А) «Ракета» должна всегда предпринимать шаги по направлению к своей цели. Б) "Ракета" должна всегда занимать 5 секунд, чтобы добраться туда. Написание класса Vector2D не проблема. У меня просто нет под рукой (а математика - не лучший мой предмет). Если это облегчает, я могу добавить это.
Питер
Самый простой способ сделать это - использовать сплайн Эрмита и перенести параметрическое значение.
Стивен Срун

Ответы:

11

Редактирование обнадеживает. :)

Хорошо, вот простой цикл обновления ...

Предполагая, что когда мы запускаем ракету, мы инициализируем remainingFlightTime = 5fпотом ...

void UpdateMissile(float deltaTime)
{
   remainingFlightTime -= deltaTime;

   // At the end of the trajectory, snap to target & explode.
   // The math will put us there anyway, but this saves
   // on fancy logic related to overshooting. ;)
   if(remainingFlightTime <= 0f)
   {
      myX = targetX;
      myY = targetY;
      MissileImpact();
      return;
   }

   // Compute straight-line velocity that will take us
   // to the target in exactly the time remaining.
   velocityX = (targetX - myX)/remainingFlightTime;
   velocityY = (targetY - myY)/remainingFlightTime;

   // Integrate the velocity into the position.
   myX += velocityX * deltaTime;
   myY += velocityY * deltaTime;
}
ДМГригорий
источник
1
Этот метод не заставляет «ракету» вращаться вокруг точки запуска в полете. +1
Джон
0

Почему бы не перенести позицию и не обновить целевой пункт назначения по мере его изменения?

Возможно, вам придется посмотреть, как работает lerping, но это будет выглядеть примерно так:

public position startMarker;
public float duration = 5.0f;
private float startTime;
void Launch() {
    startTime = Time.time;
}
void Update() {
    float distCovered = (Time.time - startTime) / duration;
    missile.position = Vector3.Lerp(startMarker.position, target.position, distCovered);
}

Лерпя, вы в основном меняете положение объекта в течение определенного промежутка времени, так что вы можете сказать, что вы находитесь на 50% пути от А до В, и объект будет размещен там. Лерпинг прямой, поэтому вы всегда будете двигаться к цели (как вы хотите в комментариях).

user3797758
источник
да ладно, мой плохой ... я думаю, вот что произойдет, если вы попытаетесь написать код в 3 часа ночи. изменил ответ, чтобы исправить ошибку
user3797758