Як можна запобігти наведенням ракет навколо орбіт?


78

Я розвиваю 2D космічну гру без тертя, і мені здається, що дуже легко зробити орбітальну ракетну орбіту своєю ціллю. Мені цікаво стратегій проти орбіти.

Простим прикладом є навісна ракета, яка просто прискорюється безпосередньо до своєї цілі. Якби ця ціль рухалася перпендикулярно до траєкторії ракети, то зупинилася, прискорення ракети до цілі було б недостатньо для подолання власної швидкості, і ракета могла бути загнана на орбіту навколо цілі, як зображено:

Проблема орбіти

  • У кадрі 1 ракета прямує прямо до своєї цілі, жодних проблем.
  • У кадрі 2 ціль перемістилася в нове положення, як показано. Ракета продовжує прискорюватись безпосередньо до цілі (червоного кольору), продовжуючи рухатись до місця, де раніше знаходилась мета (чорного кольору) через існуючу швидкість.
  • У кадрі 3 швидкість ракети продовжує нести ракету навколо сторони цілі (чорна), тоді як вектор прискорення відчайдушно намагається тягнути ракету до цілі.
  • У рамах 4 і далі ракета потрапляє на потенційно стійку орбіту навколо цілі і ніколи не досягає своєї мети. Чорні стрілки позначають вектор швидкості, тоді як червоні лінії вказують вектори прискорення в той самий момент часу.

Враховуючи те, що в космосі немає тертя, немає нічого, щоб уповільнити швидкість ракети вниз і зруйнувати орбіту. Можливим рішенням було б націлитись "за" ціль, і це призведе до закриття орбіти, але як це робиться з точки зору програмування?

Як змусити ракету навішування досягти своєї цілі?


9
Це насправді надзвичайно класний спосіб виведення орбіти штук.
Дерек

Це нагадує мені інтеграцію Ейлера. Все, що вам потрібно зробити, - це зробити свій крок часу нескінченно малим, вирішена проблема!
Джефф

Я хочу реалізувати цей ефект у своїй грі! : D
Золомон


6
@Deza Це саме визначення орбіти. Об'єкт орбіти прискорюється відцентровою силою в напрямку до центру якогось іншого об'єкта.
бобобобо

Відповіді:


49

Перш за все, слід зробити всі розрахунки щодо того, яке прискорення слід застосувати в системі відліку ракети (саме там ракета нерухома, а все інше рухається навколо неї, також часто називається "об'єктами координат" або "локальними координатами" в ігрових двигунах, хоча в нашому випадку ми також хочемо, щоб ця швидкість була точно рівною нулю).

Тоді ідея полягає не у тому, щоб не ставити собі за мету, а націлитись на місце, де ціль опиниться в очікуваний час удару. Тож загальний алгоритм виглядає приблизно так:

  1. Підрахуйте, скільки часу знадобиться ракеті для досягнення цілі. Якщо ціль летить прямо на неї (пам’ятайте, ракета нерухома ), це може бути таким же простим, як обчислення відстані / швидкості , в інших випадках може бути складніше. Якщо мета може спробувати ухилитися, ви все одно не зможете зробити ідеальну оцінку, тож добре не бути дуже точним.

  2. Припускаючи постійну швидкість (оцінка 1-го ступеня) або постійне прискорення (оцінка 2-го ступеня) цілі, обчисліть, де вона буде в розрахунковий час вище.

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

  4. Перепроектуйте прискорення назад із системи відліку ракети на глобальну, використовуйте це.

Важлива частина тут полягає в тому, щоб оцінити час у грубій бальній смузі, а також не забувати можливості прискорення ракети при цьому. Наприклад, кращою оцінкою "ціль прямо попереду нас і летить у нашому напрямку" було б вирішити рівняння.

відстань = швидкість х час + 1/2 х прискорення х час 2

... для часу (використовуйте негативну швидкість для об'єктів , що летять прямо в стороні від ракети), з рішенням , яке ви шукаєте , використовуючи стандартну квадратичную формулу істоти ...

час = (√ ( швидкість 2 + 2 x прискорення x відстань ) - швидкість ) / прискорення

Додавання додаткових параметрів - перетягування, наприклад - швидко перетворює це на диференціальні рівняння без алгебраїчних рішень. Ось чому ракетна наука настільки важка.


Я думаю, що це саме те, що мені потрібно. Я ніколи раніше не думав про місцеві координати.
Джон Макдональд

5
Чудова відповідь. Як бічне зауваження, багато ракет стеження призначені для автоматичного вибуху на цих умовах: 1) потрапляння на певну відстань від колії та 2) відстань до колії збільшується. Це може додати трохи приємної поведінки за невеликих витрат.
Патрік Х'юз

1
Це чудова відповідь. Я закінчив, використовуючи постійне прискорення для зброї (я вважав, що це найбільш реально), підрахував час, який знадобиться, щоб приїхати (переупорядкуйте d = v t + 1/2 * a t * t і вирішіть для t). Таємний соус полягає у зворотному підрахунку часу, щоб спроектувати, де цілі буде надана його поточна швидкість та прогнозований час для впливу. Добре працює.
bobobobo

1
Я здогадуюсь, що це тип алгоритму підрахунку мертвих
bobobobo

42

@Martin Sojka вже сказала вам, що робити. Замість вдосконалення його відповіді я хочу запропонувати вам ще один простіший підхід: DELOCK

Як я вже говорив у проектованій траєкторії транспортного засобу? , об'єкти з обмеженими можливостями кермування "проектують" пару тіньових кіл: дві області, до яких неможливо дістатись за допомогою прямого керування (торус і гіпертор у більших розмірах).

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

Тригер переміщення можна легко обчислити, апроксимуючи торі (подвійним) конусом *:

Спусковий механізм блокування

Ви повинні просто обчислити скалярний добуток між вашим (нормалізованим) вектором напрямку та цільовим вектором переміщення ( Ціль - Об'єкт / | Ціль - Об'єкт |).

Коли скалярний добуток виходить на нуль, ваш цільовий напрямок стає перпендикулярним до вашого напрямку, що веде до кругової траєкторії **. Коли ціль потрапить у блакитний регіон, ви можете перевернути напрямок рульового управління, щоб ви могли поставити його за межі недосяжної ділянки та знову навести націлювання.

* Якщо чесно, це не конус ... - це інший вид лінійної поверхні, породженої (напів) обертом двох не паралельних прямих навколо осі, що проходять через перетин і перпендикулярно бісектрисі; Проекція на 2D площину така ж, як у подвійного конуса, але вісь обертання перпендикулярна до тієї, яка породжує конус.

** Ця траєкторія навряд чи кругла, ні еліптична, ні навіть закрита. Шанси полягають у тому, що траєкторія піде за спирографом, як шлях (гіпотрохоїд) у 2D або навіть інших монстрах у 3 та вище розмірах. До центру таких кривих ніяк не можна дістатися, і вони виглядають як кола настільки «кругової» траєкторії.


+1 Приємна ідея для випадку, коли вектор прискорення ракети обмежений перпендикулярно напрямку руху. Я не думаю, що це стосується цього питання.
Мартін Сойка

@Martin Sojka вектор прискорення можна навіть розбити на дві складові: одна радіальна, а інша дотична до напрямку. Перший розповідає, на скільки можна повернути, другий - на скільки можна прискорити / зменшити швидкість.
FxIII

1
Так, і якщо ви вільні вибирати їх відносні сили незалежно один від одного (тобто якщо напрямок і сила вектора прискорення не залежать від вектора руху), ваші "кола виключення" зникають.
Мартін Сойка

@Martin Sojka Невже не існує обмеження в силі прискорення?
FxIII

1
+1 Це дуже круто. Я ніколи раніше про це не думав. Я, мабуть, спробую використати це спільно з відповіддю @ Матіна
Джон Макдональд

8

Ваша система наведення побудована на припущенні, що прискорення прямо до цілі з часом призведе до стикання об'єктів. Оскільки це припущення є помилковим, вказівки AI, засновані на цьому припущенні, також не є успішним.

Тож перестаньте прискорюватися безпосередньо до цілі. Додайте трохи логіки, щоб визначити, чи положення мішені дещо перпендикулярне напрямку руху ракети. Якщо так, то ракеті потрібно прискорити рух до цілі, але також уповільнити її рух вперед. Отже, замість того, щоб прямувати безпосередньо до цілі, вона зміщує напрямок свого прискорення так, щоб швидкість струму в напрямку його руху сповільнювалася.

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

Останнє: жодна система наведення не буде досконалою. Причина, по якій ракети можуть перехоплювати цілі в реальному житті, полягає в тому, що цілі рухаються набагато повільніше, ніж самі ракети, а цілі не особливо спритні (відносно кажучи). Якщо ваші ракети не будуть у багато разів швидшими, ніж цілі, які вони переслідують, то вони пропустять багато.


2
"Цілі не особливо спритні", чи не так?
bobobobo

5

Найпростіший і найсучасніший метод для використання в іграх (і в реальному житті) - пропорційна навігація.

Під Constant підшипник Зменшення діапазону (CBDR) логіки, коли два об'єкти (ракетні та цільові) подорожують в тому ж напрямку без зміни візування між друг з одним, вони будуть стикатися.

Лінія прицілу, або Лінія прицілу (LOS) - уявна лінія між ракетою та ціллю - вектор між положенням ракети та положенням цілі. Швидкість кутового зміни цього LOS - це коефіцієнт обертання LOS.

Коли коефіцієнт обертання LOS стає нульовим, то видовище більше не змінюється - два об'єкти зараз перебувають у колізійному ході. Подумайте про себе, як переслідувати когось, граючи у футбол. Якщо ви будете вести його таким чином, щоб його тіло виглядало «замерзлим» у вашому полі зору (прицільна лінія між вами та ним більше не змінюється), ви зіткнетесь з ним до тих пір, поки не будете підтримувати своє прискорення бігу, щоб його тіло здавалося замерзлим у ваш погляд.

У режимі пропорційної навігації (ПН) ракета прискорює "N" в рази швидше, ніж швидкість обертання LOS. Це змусить ракету вести ціль до тих пір, поки швидкість обертання ЛОС не стане нульовою - тобто ракета і ціль не стануть замороженими в стані, оскільки прицільна лінія більше не змінюється - вони тепер перебувають у напрямку зіткнення. Змінна "N" відома як Константа навігації (постійний множник).

Команду наведення ракети слід надати наступним чином:

Прискорення = швидкість закриття * N * швидкість втрати

Швидкість LOS можна легко отримати, вимірюючи вектор LOS (цільове положення - положення ракети) та зберігаючи його змінну. Вектор LOS з нового кадру (LOS1) віднімається LOS-вектором зі старого кадру (LOS0) для створення дельти LOS - тепер у вас є примітивна швидкість обертання LOS.

Щоб спростити швидкість закриття, ви можете просто використовувати поточний вектор LOS на його місці, таким чином:

Прискорення = (target_pos - missile_pos) * LOS_delta * N

N - константа навігації - в реальному світі вона зазвичай встановлюється від 3 до 5, але фактична працездатна цифра в грі дещо залежить від швидкості вибірки, з якою ви отримуєте коефіцієнт LOS / дельта. Спробуйте випадкове число (починати з 3) і збільшити до 1500, 2000 і т.д., поки ви не побачите бажаний провідний ефект у грі. Зауважте, що чим вище навігаційна константа, тим швидше ракета відреагує на зміни швидкості LOS на початку польоту. Якщо ваша імітаційна модель ракетної навігації є дещо реалістичною, надмірна навігаційна константа може перевантажувати аеродинамічну здатність вашої ракети, тому вам слід використовувати збалансоване число на основі спроб та помилок.


4

Як вказують інші відповіді Мартіна і Ніколя, ви, мабуть, хочете направляти свою ракету не безпосередньо в ціль, а таким чином, що згодом змусить її зіткнутися з ціллю. Однак метод, описаний Мартіном, є складним, а той, який описав Нікол, є неефективним.

Більш простий спосіб - але все ще досить ефективний - спрямовувати ракету шляхом регулювання її кута відповідно до зміни кута між ракетою та ціллю. На кожному галочці ви обчислюєте кут від ракети до цілі та порівнюєте його з кутом попереднього галочки. Різниця полягає в точній різниці, яку ви хочете зробити під кутом ракети. Отже, якщо кут в одному галочці становив 0,77, а в іншому - 0,75, потрібно відрегулювати кут ракети на -0,02. Цей метод простий, і поки ціль знаходиться "перед" ракети, це дуже ефективно з точки зору обраного маршруту. Це також стосується будь-якої кількості розмірів, а не лише в 2d.

Майте на увазі, однак:

  • Цей спосіб порушується, якщо ракета і ціль мають однакову швидкість і рухаються паралельно. Що ж, теоретично все ще складається план зіткнення ракети, це просто займає нескінченний час :) на практиці ракета завжди повинна бути швидшою, ніж ціль, але якщо вони мають однакову швидкість, вам потрібно додати кутовий кейс, щоб визначити, чи є вони паралельними .

  • Метод порушується, якщо ціль і ракета летять по точно одній лінії, але в протилежних напрямках. Це реально не може відбутися в реальному світі, але не дуже рідкість в дискретній грі. Вам потрібно додати перевірку на кутовий випадок до вищевказаного алгоритму, щоб перевірити це.

  • Якщо ваша ракета має обмежену здатність до повороту, просто змушуйте її робити максимальний оборот кожного разу, коли їй потрібно повернути більше. Поки ракета буде досить далеко, вона все одно буде працювати. Якщо це занадто близько, дивіться останню кулю.

  • Не забудьте бути поблажливими при перевірці зіткнення. У реальному світі багато ракет покладаються на свою боєголовку для створення «зони вбивства», тому їм потрібно лише наблизитися до цілі, а не насправді зіткнутися з нею.

  • Нарешті, на практиці ракета все ж може пропустити , що повертає нас до вашого початкового питання. Я думаю, що хороший спосіб - справді відключити наведення на декілька кліщів, дозволяючи йому досягти деякої відстані, а потім змусити його знову навести курси. Я думаю, що запропонований fxiii метод виявлення мертвих зон - це чудовий спосіб виявити, коли вам потрібно вимкнути налагодження.


1

Кілька простих варіантів, які були визнані "досить хорошими" для ігор, над якими я працював у минулому:

1) Якщо дозвіл сцени, на яку ви дивитесь, дозволяє це, то об'єкт може вибухнути, коли він знаходиться поруч із ціллю (що, як я вважаю, найбільш поширені ракети денного самонаведення фактично працюють у будь-якому випадку). Якщо ваш дальність орбіти приблизно вдвічі перевищує розмір об'єкта, то це, ймовірно, не спрацює для вас, оскільки це просто буде погано виглядати.

Якщо ваша кінцева мета у вашому рішенні - просто переконатися, що ваша ракета потрапила в ціль, то я все за те, щоб я лише потрапила в ціль. Знову ж, це буде просто залежати від того, як виглядає рішення.

2) Якщо ви виявите, що ваша ракета знаходиться під прямим кутом до вашої цілі, це може бути точка, коли замок "ламається", а ракета просто рухається прямо, якщо ціль не потрапить "перед" ракетою знову.

Я завжди віддаю перевагу простим рішенням, коли це можливо. Якщо ви робите гру, в якій наводиться ракета - це лише одне із застосовуваних озброєнь, то ви, швидше за все, зможете уникнути цього, оскільки гравці, швидше за все, вистрілять із залпа, а потім якнайшвидше повернуться до своєї зброї з постійною участю. Якщо ви робите симуляцію ракет, то однозначно один з інших відповідей - кращий вибір.

Сподіваюся, це допомагає.


0

Як було сказано, ви повинні спрямовувати ракету на те, куди очікується мета, коли ви потрапите туди, а не на те, де зараз знаходиться ціль. Це не дозволить ракетам НАЙБІЛЬШЕ вийти на орбіту, але орбіта все-таки можлива, якщо ціль ухиляється як раз. Це законна тактика, яку застосовують пілоти літаків для ухилення вхідних ракет - оскільки ракета іде набагато швидше, ніж ви, вона матиме більший радіус повороту і різкий тріск в потрібний момент, змушує її продовжуватися. (Хоча ви все ще можете загрожувати через детонацію близькості.)

Оскільки ми маємо справу з ракетою, яка все ще може відслідковувати і все ще має тягу, ви отримуєте ситуацію на орбіті, якщо ціль ухиляється в одну з зон, про яку йдеться у публікації FxIII.

Однак я не згоден з його вирішенням проблеми. Натомість я б програмував ракети таким чином:

якщо ракета тягнеться на 90 градусів до її лінії руху на 360 градусів руху, ви перебуваєте на орбіті. Відрегулюйте тягу на 120 градусів від лінії руху. Орбіта ракети буде розширюватися, оскільки вона не обертається так сильно, але ракета також сповільниться, що дозволить їй маневрувати краще. Коли дальність націлювання на ціль відкривається до 1,25x, діаметр мертвої зони (зауважте, що цей діаметр базується просто і тільки на швидкості ракети, не потрібен складний розрахунок під час виконання), ракета повертається до своєї нормальної поведінки стеження.

Крім того, використовуйте тупіші голови шукачів - коли дальність націлювання перестає рахувати вас, детонізуючи.


0

Я знаю, що це давнє запитання, але я думаю, що у відповідях, що даються досі, було пропущено щось. У первісному питанні, ракеті (або будь-якій іншій) було сказано, щоб прискорити до положення цілі. Кілька відповідей вказували на те, що це було неправильно, і вам слід прискоритись до того місця, де ви думаєте, що ціль буде в якийсь пізній час. Це краще, але все ж неправильно.

Те, що ви насправді хочете зробити, - це не прискорити рух до цілі, а рухатися до цілі. Спосіб подумати над цим - встановити бажану швидкість, спрямовану на ціль (або проекцію розташування цілі), а потім розібратися, яке прискорення ви могли найкраще застосувати (враховуючи будь-які обмеження, тобто ракета, ймовірно, не може прискорити безпосередньо у зворотному напрямку) для досягнення бажаної швидкості (пам'ятаючи, що швидкість - вектор).

Ось відпрацьований приклад, який я реалізував сьогодні вранці, в моєму випадку для гравця AI в спортивній симуляційній грі, де гравець намагається переслідувати свого суперника. Рух регулюється стандартною моделлю 'удар-дрейф', де прискорення застосовуються на початку часового кроку для оновлення швидкостей, а потім об’єкти дрейфують із такою швидкістю протягом тривалості часового кроку.

Я б опублікував виведення цього, але я виявив, що на цьому сайті не підтримується розмітка математики. Бу! Вам просто доведеться вірити, що це оптимальне рішення, маючи на увазі, що у мене немає обмежень щодо напрямку прискорення, що не стосується об'єкта ракетного типу, тому це вимагало б додаткових обмежень.

Код є в python, але його слід читати на будь-якому мовному тлі. Для простоти я припускаю, що кожен крок часу має довжину 1 і виражати швидкість і прискорення у відповідних одиницях, щоб це відобразити.

self.x = # current x co-ordinate
self.y = # current y co-ordinate
self.angle = # current angle of motion
self.current_speed = # current magnitude of the velocity
self.acc # Maximum acceleration player can exert on themselves
target_x = # x co-ordinate of target position or projection of it
target_y = # y co-ordinate of target position or projection of it
vx = self.current_speed * math.cos(self.angle) # current velocity x component
vy = self.current_speed * math.sin(self.angle) # current velocity y component
# Find best direction to accelerate
acc_angle = math.atan2(self.x + vx - target_x,self.y + vy - target_y)

Зауважимо, що функція atan2 (a, b) обчислює зворотний загар a / b, але забезпечує кути, що знаходяться у правильному квадранті кола, для чого потрібно знати ознаки як a, так і b.

У моєму випадку, коли я маю прискорення, я застосовую це для оновлення швидкості на

vx_new = vx + self.acc * math.cos(acc_angle)
vy_new = vy + self.acc * math.sin(acc_angle)
self.current_speed = math.sqrt( vx_new**2 + vy_new**2)
self.angle = math.atan2(vy_new,vx_new)

Я також перевіряю нову швидкість проти максимальної швидкості, залежної від гравця, і обмежую її. У випадку з ракетою, автомобілем або чимось із максимальною швидкістю повороту (у градусах на галочку) ви можете просто подивитися на поточний кут руху проти обчисленого ідеалу, і якщо ця зміна більша від дозволеної, просто змініть кут на якомога більше до ідеалу.

Для всіх, хто зацікавлений у виведенні цього, я записав відстань між гравцем та ціллю після часового кроку, з точки зору початкової позиції, швидкості, швидкості прискорення та кута прискорення, а потім взяв похідну щодо кута прискорення. Встановивши, що до нуля, знаходяться мінімуми відстані гравця-цілі після часового кроку як функції кута прискорення, який саме ми хочемо знати. Цікаво, що, хоча швидкість прискорення спочатку була в рівняннях, вона скасовує створення оптимального напрямку незалежним від того, наскільки ви насправді здатні прискорити.


У деяких сценаріях я майже радив би встановлювати швидкість безпосередньо, хоча це може бути важко інтегруватися з фізичною системою, в основному залежною від сили. Якщо це гра, в якій ракети вистрілюються регулярно, при цьому "ухилення" не є помітним ігровим механіком, то, можливо, ви захочете уникнути невеликого ризику, коли фізика стане на шляху, і просто запевнити, що цей механік працює так, як гравець цього очікує. до кожного разу. Це може мати більше сенсу в, скажімо, RTS, ніж у космічній грі.
Katana314

0

Ви використовуєте постійну швидкість повороту. Саме це викликає приємну ідеально кругову орбіту.

Більш реалістичним підходом для системи наведення було б змінити швидкість повороту на зворотно цільовій відстані (менша відстань -> більша швидкість повороту). Це дало б спіраль, а не орбіту, і гарантувало зіткнення з більш повільною ціллю.

Це також дає набагато реалістичніший маршрут польоту. Постійна швидкість повороту неприродно ідеальна. Ви також можете додати випадкові зміни до швидкості повороту, щоб імітувати турбулентність. Знову ж таки, набагато реалістичніше, і насправді можна уникнути стаціонарних сценаріїв орбіти.

Не потрібно часткових рівнянь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.