Низкая производительность при реализации A * в игре Tower Defense

9

Я делаю игру Tower Defense во Flash без предопределенного пути.

Хотя моя сетка 40х40 (маленькая?), A * испытывает трудности при пересчете каждый раз. Поэтому я сделал свою собственную модификацию, чтобы облегчить пересчет, и количество затронутых ячеек упало примерно до 900 (при модификации около корня). Он все еще замораживается в течение очень короткого, но обнаруживаемого периода времени, когда устанавливается новая башня.

Это проблема реализации или 40х40 слишком много?

Редактировать:

Структура моего кода:

  • Все данные сохраняются в 2d массиве ячеек.
  • Каждая ячейка содержит своего родителя в направлении пути (1-8 по часовой стрелке) и битовый кодированный массив ее дочерних элементов в пути (каждый бит представляет дочерний элемент).
  • Поиск осуществляется по A * с оценкой евклидова расстояния.
Дани
источник
Вам нужно быть более конкретным здесь. Мы не знаем, как выглядит ваш код, как он структурирован и т. Д., И поэтому мы не можем сделать какие-либо выводы о том, что делает его медленным.
Шон Джеймс
1
Когда я в последний раз внедрил A *, я помню, что он проходил через сетку 64x64 в течение не более 1 мс. Так что да, похоже, проблема с вашей реализацией. Я предлагаю опубликовать ваш код или его суть, чтобы мы могли помочь вам в дальнейшем.
Марк Мюллер
Смотрите правку, которую я добавил
Дани
1
Если 40x40 слишком медленный, есть вероятность, что вы делаете что-то очень неправильно. Либо опубликуйте свой код, либо профилируйте его. Кроме того, увеличьте масштаб и посмотрите, что произойдет - если сетка 80x80 занимает больше четырех раз, у вас есть что-то чрезвычайно сломанное.
ZorbaTHut
Название может быть немного более информативным, пожалуйста?
Tenpn

Ответы:

4

Я не могу комментировать, но первый профиль во Flex, все остальное - гипотеза.

Джонатан Фишофф
источник
Как мне профилировать флеш проект во флексе?
Дани
Да и нет. Я не думаю, что вы загружаете флеш-проект напрямую. Я думаю, что вы могли бы профилировать SWF без источника и все же получить информацию об уровне функции, хотя. Я бы сделал поиск в Google для «профилирования проекта Flash во Flex» или тому подобное. Я сделал и получил это: flexblog.edchipman.ca/…, который выглядит многообещающим.
Джонатан Фишофф
Спасибо, действительно помогли мне найти проблемную часть (не было в алгоритме, см. Комментарий к вопросу)
Дани
13

Я предполагаю, что TD это «Tower Defense»

Я думаю, что A * идет за борт для этого.

В начале игры флуд заполняет игровую область из точек выхода, чтобы создать карту движения:

 |---------|
 |5|4|3|3|3|
 |5|4|3|2|2|
->5|4|3|2|1->
 |5|4|3|2|2|
 |5|4|3|3|3|
 |---------|

и движение всегда к квадрату с более низким значением.

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

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

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

Skizz
источник
6
Повторное заполнение флудом обходится дороже, чем выполнение A * для небольшого количества блоков - примерно, длины платы - по крайней мере, в алгоритмическом смысле (и поскольку это Flash, неалгоритмические константы, такие как макет памяти, вероятно, могут ' использоваться очень эффективно). Тем не менее, это очень хорошая модель для многих взаимодействующих устройств и называется коллективной диффузией - scalablegamedesign.cs.colorado.edu/wiki/Collaborative_Diffusion .
@ Джо Wreschnig: вау хорошая ссылка. Я использовал эту технику раньше, но никогда не знал, как она называется. Спасибо.
Tenpn
@ Джо, пока на карте есть хотя бы несколько барьеров, я не думаю, что это будет более неэффективно, чем вызов A *. То есть, я полагаю, что только для широко открытой, почти безбарьерной карты с небольшим количеством юнитов это может быть хуже.
edA-qa mort-ora-y
@edA: по определению заливка должна в конечном итоге касаться каждой доступной точки на карте; A * обеспечивает проверенные верхние границы того, сколько точек оно должно касаться, что является не более чем каждой доступной точкой на карте и обычно намного меньше. Заливка потока - это более простой алгоритм для оптимизации таких вещей, как макет памяти, но, как я уже сказал, во Flash это, вероятно, не имеет значения.
@ Джо, это то, что я утверждаю, что даже при небольшом количестве башен A *, вероятно, коснется почти всех пространств. Но для N монстров нужно только превышать total_squares / N, чтобы быть менее эффективным, чем заливка.
edA-qa mort-ora-y
2

Странно, я думал, что ответил на это, но ответа, похоже, больше нет. Сделайте свой алгоритм поиска таким, чтобы он мог обновляться в несколько этапов, чтобы при установке башни и воспроизведении анимации вы могли выполнять каждый кадр немного, и у вас будет где-то от полсекунды до секунды для обновления A * без заметной паузы. Это задержка - если вы не можете ускорить это, найдите способ скрыть это. Воспроизведение анимации при размещении башни было бы естественным для игры, и, я думаю, это хорошее место, где ее можно спрятать.

Кая
источник
Это хорошая идея в целом, но плохая для этого конкретного вопроса. A * на такой маленькой сетке должен быть почти мгновенным, не занимая значительное количество времени.
Давр
Справедливо. Это единственный ответ, который я мог бы дать, который решил бы проблему, не зная деталей реализации, которые вызвали бы замедление.
Кай
0

Для начала вы можете изменить свой массив на вектор - это даст вам некоторые улучшения скорости. Разместите код, и мы сможем предложить больше оптимизаций.

Iain
источник
0

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

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

jhocking
источник
На это ответили почти год назад, и столкнулись только из-за редакторской работы Грейс. (Это не имело никакого отношения к слишком
Спасибо, что дали мне знать. Я не заметил даты.
Джокинг