Я работаю над тем, чтобы улучшить поиск врагов моей игры. Прямо сейчас они просто постоянно движутся к точной позиции игрока, вычисляя угол между собой и игроками и двигаясь в этом направлении. У меня также есть алгоритм флокирования, который не дает врагам складываться друг на друга, поэтому они будут объединяться в группы, а не пересекаются друг с другом.
Однако теперь, когда я добавил карту на основе тайлов, мне нужно, чтобы враги также могли обходить препятствия и стены, например. Сначала я попытался добавить значение разделения к «не проходимым» плиткам, чтобы алгоритм флокирования рассматривал стены и препятствия как объекты, от которых нужно отойти. Мне еще предстоит выяснить, возможно ли это, потому что мой первоначальный тест показал, что враги попадают в невидимую «стену», где нет неприступных тайлов, но по какой-то причине они поражают ее и начинают разбрасывать.
Мне было интересно, не слишком ли сложно вычислить путь к игроку, используя A *, а затем использовать алгоритм флокирования, чтобы предотвратить комкование. Первоначально моя игра собиралась быть стрелялкой на основе волн, но вместо этого я решил сделать ее ориентированной на уровни в духе Hotline Miami, так что, скорее всего, у меня будет меньше врагов со случайной ордой, и я просто сделаю их сильнее.
Это жизнеспособное решение? Я использую Java с Slick2D в качестве игрового движка. Или есть лучшее решение / алгоритм, который решает обе эти проблемы?
источник
Ответы:
Это звучит как сценарий использования полей потока.
В этом методе вы выполняете один запрос поиска пути от объекта (ов) игрока, отмечая каждую ячейку, с которой вы столкнулись, ячейкой, с которой вы его достигли.
Если все ваши плитки / ребра имеют одинаковую стоимость обхода, то вы можете использовать простой поиск в ширину для этого. В противном случае алгоритм Дейкстры (например, A * без цели / эвристики) работает.
Это создает поле потока: справочную таблицу, которая связывает каждую ячейку со следующим шагом по направлению к ближайшему объекту игрока из этой позиции.
Теперь каждый из ваших врагов может найти свою текущую позицию в поле потока, чтобы найти следующий шаг в своем кратчайшем пути, избегающем препятствий, к ближайшему объекту игрока, при этом каждый из них не выполняет свой собственный запрос поиска пути.
Это масштабируется все лучше и лучше, чем больше врагов в вашей пастве. Для одного врага это дороже, чем A *, потому что он ищет всю карту (хотя вы можете заблаговременно, когда вы доберетесь до всех агентов, ищущих пути). Но когда вы добавляете больше врагов, они получают все больше и больше затрат на поиск пути, вычисляя сегменты общего пути один раз, а не снова и снова. Вы также получаете преимущество от того факта, что BFS / Dijkdtra проще, чем A *, и, как правило, дешевле оценивать для каждой проверяемой ячейки.
Именно там, где достигается точка безубыточности, от отдельного A * до более дешевого, до A * с более дешевым запоминанием (где вы повторно используете некоторые результаты для прошлого запроса поиска пути для ускорения следующего), чтобы потоки полей были дешевле, будет зависеть от вашей реализации, количества агентов и размера вашей карты. Но если вы когда-либо планируете большой рой врагов, приближающихся с нескольких направлений в ограниченном пространстве, одно поле потока почти наверняка будет дешевле, чем итерация A *.
В качестве крайнего примера, вы можете увидеть здесь видео с 20 000 агентов, которые все одновременно находят пути в достаточно маленькой сетке .
источник
A * не тяжелая производительность. Я бы подошел к этой ситуации, варьируя алгоритмы. Делайте A * время от времени, и между ними проверьте, свободен ли следующий шаг или вам нужно уклонение.
Например, отследите расстояние игроков от целевого местоположения A *, если оно превышает пороговое значение, пересчитайте *, а затем просто обновите движения. Большинство игр используют комбинацию путевых точек, например, упрощенную сетку для поиска пути и логику, которая обрабатывает перемещение между путевыми точками с помощью алгоритмов уклонения, использующих лучевые трансляции. По моему мнению, агенты пытаются сбежать в дальнюю точку маршрута, маневрируя вокруг препятствий, находящихся поблизости.
Лучше всего поработать с конечными автоматами здесь и почитать книгу Мэтта Бакленда "Программирование AI на примере". Книга предлагает проверенные методы для вашей проблемы и детали математики требуется. Исходный код из книги доступен в Интернете; книга написана на C ++, но некоторые переводы (включая Java) доступны.
источник
Мало того, что это осуществимо, я считаю, что это было сделано в коммерческой игре в 90-х годах - BattleZone (1998).
В этой игре были трехмерные юниты со свободным движением, не основанным на тайлах, и базовая конструкция на основе тайлов.
Вот как это работает:
Во-первых, A * или что-то подобное (вероятно, вариация A * со строгими ограничениями на длину пути, который он может найти, поэтому он никогда не требует слишком много ресурсов для запуска, но не всегда находит путь до места назначения) будет использоваться, чтобы найти путь для hovertank, чтобы добраться до его пункта назначения, не застревая в основанных на плитке препятствиях.
Тогда танк будет летать вокруг неиспользованного пространства, как если бы он был привлечен к центру соседней плитки на своем пути и отражен препятствиями, другими соседними танками и т. Д.
источник