Как реализовать умного врага в перестрелке?

13

Представьте себе очень простую игру, которую мы все знаем:

стреляй 1

Ты игрок (зеленый). Ваше движение ограничено Xосью. Наш враг (или враги) находится вверху экрана, его движение также ограничено Xосью. Игрок стреляет пулями (желтым цветом) по врагу.

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

взвешенная стрельба

Существует два веса: «вес пули» (серый) - это опасность, создаваемая пулей. Чем ближе пуля к врагу, тем выше «вес пули» ( 0..1где 1 - самая большая опасность). Дорожки без пули имеют вес 0. Второй вес - это «дистанционный вес» (салатовый). Для каждой полосы я добавляю 0.2стоимость движения (это значение теперь произвольно и может быть изменено).

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

Итак, вот что я ищу:

полное уничтожение

  • Нужно найти выход сквозь пулевую бурю, даже когда нет места, которое не навязывает угрозу пули.
  • Враг может надежно уклоняться от пуль, выбирая оптимальное (или почти оптимальное) решение.
  • Алгоритм должен учитывать скорость движения пуль (так как они могут двигаться с разными скоростями).
  • Способы настройки алгоритма, чтобы можно было применять различные уровни сложности (немой для сверхразумных врагов).
  • Алгоритм должен позволять разные цели, так как противник не только хочет уклоняться от пуль, но и уметь стрелять в игрока. Это означает, что позиции, где противник может стрелять в игрока, должны быть предпочтительными при уклонении от пуль.

Так как бы вы занялись этим? В отличие от других игр этого жанра, я хотел бы иметь только несколько, но очень «умелых» врагов вместо массы тупых врагов.

bummzack
источник
2
Рассматривали ли вы использовать что-то вроде поведения руля? Там один для избежания препятствий в частности: red3d.com/cwr/steer/Obstacle.html
Тетрадь
@Tetrad Я думал о рулевом поведении ... также потому, что его можно переключать, например, "попытаться выстрелить в игрока" и когда впереди опасность, переключиться на "уклонение". Я боюсь, что 1D-версия (это то, с чем я в основном имею дело) будет слишком глупой, чтобы принимать правильные решения. Я могу ошибаться, хотя.
bummzack

Ответы:

8

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

Градиент должен сочетаться:

  • близость
  • Скорость
  • Ширина пули
  • (опционально) Положение целей (игроков)

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

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

Если потребность в огне больше, чем необходимость двигаться, тогда сделайте это; Ваш код также может определить это по тому, насколько они различаются. Вы можете реализовать это как часть базового графика, и в этом случае позиция игрока уменьшает окружающие значения на графике (при условии, что враги тяготеют к самой низкой точке), который объединяет все процессы принятия решений в один график, или вы можете сохранить " График «Желание уволить» отделен от основного графа «Желание уклониться», который предложит вам более прямой контроль.

IRL, я бы не стал уклоняться от снаряда до тех пор, пока он не окажется на расстоянии, которое, насколько я знаю, при моей максимальной скорости уклонения становится трудно избежать. Опыт из первых рук бросать камни, как парень. Пуля на расстоянии х, движущаяся со скоростью у, имеет такой же уровень опасности, как пуля на расстоянии 2х, летящем на 2й. Так что это должно быть учтено правильно.

Способы настройки алгоритма сложности противника включают

  • введение задержки при обновлении графика (Born Too Slow)
  • введение случайных, локализованных неточностей в граф
  • просто из-за того, что враги не подчиняются тому, что им говорит график, по последовательности обновлений (скажем, от 1 до 10 кадров) из-за явной лени ИИ

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

инженер
источник
1
Уважаемый Ник. Я реализовал небольшую тестовую версию этого поведения во флэш-памяти, и я очень доволен результатом (пули появляются случайным образом). В настоящее время я использую 3 градиента, один для угрозы, стоимость перемещения и статический для краев (так что края экрана менее желательны). Они визуализируются во флэш-приложении. Я чувствую, что с некоторыми изменениями я могу добиться очень хороших результатов, а также учитывать другие веса, такие как стрельба. Большое спасибо, приятель.
Bummzack
1
Эй, @bummzack, приятель, это классная маленькая демонстрация! Ваш взгляд на проблему был для меня новым и выглядел интересным - я рад видеть, что это работает! Рад помочь с этим, и спасибо, что поделились.
Инженер
7

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

    E    
B  B**B
  B***B  B
 B***B   B
B**B** B 
 B**B**BB
B*****B B
      P

E = враг
B = пуля
P = игрок
* = варианты пути к нижней части экрана

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

Начните с плохого персонажа и отметьте безопасные позиции в пустых местах слева внизу, прямо внизу и внизу справа. Затем рассмотрите каждое безопасное пространство, которое вы только что создали, и повторите. Если в любое время вы обнаружите, что ниже нет безопасных мест, отметьте это место как небезопасное и вернитесь назад.

Qwerky
источник
1
Интересный подход. Я боюсь, что это довольно дорого, хотя среда меняется очень быстро, и сложно использовать общие алгоритмы поиска путей, так как они лучше всего работают с дискретными «картами».
bummzack
Это не должно быть слишком дорого, не забывайте, что вам нужно только вычислять нижний ряд каждый ход, вам не нужно пересчитывать все это.
Qwerky
@bummzack Среда не "быстрая", по крайней мере, с точки зрения компьютера. Для разработчика игр вы должны понимать, что почти каждая игра основана на шаге, это примерно размер этого шага. Но на каждом этапе можно проводить расчеты, поэтому решение Qwerky - это то, что вам нужно.
Deele
На самом деле, я согласен с @bummzack. Хотя этот подход логически устойчив, он будет более дорогим, чем предложенный в этом вопросе одномерный подход. Может быть, преждевременная оптимизация, но я считаю, что такой подход гораздо элегантнее. Смотрите мой ответ для уточнения этого.
инженер
2
Вероятно, это правильный ответ, но не совсем реалистичный . В то время, когда врагу требуется проработать путь, поле может иметь еще один набор пуль, полностью нарушающий путь, а это значит, что пересчет пути был бы необходимостью. И пересчет это сука . Кроме того, ваша идея обратного распространения до точки, где это было безопасно, делает его еще дороже! @ Ник Виггилл Я не думаю, что это преждевременная оптимизация, просто хорошее предвидение, чтобы вы не пнули себя в промежность.
Рэй Дей