* Алгоритм тактичних RPG?


15

Я заплутався з написанням дійсно поганої тактичної RPG в C ++. Поки що у мене є 2D карта плиток, і щойно я отримав алгоритм A *, який працює на основі псевдокоду у вікіпедії .

Але справжні тактичні РПГ не просто знаходять найкращий шлях на плоскій площині і рухаються туди. Зазвичай вони мають обмежений діапазон переміщення і повинні підніматися вгору або вниз. Якщо ви коли-небудь грали у Final Fantasy Tactics, на них впливали б статистики Move and Jump. Тут я заблукаю. Як я можу змінити алгоритм A *, щоб він знайшов найкращий шлях до цілі, але шлях має лише стільки плиток? Як слід брати до уваги перепади висоти та статистику стрибків? Як здійснити стрибки через проміжок?

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


5
Я не знаю, чому дальність переміщення - проблема. Знайдіть найкоротший шлях, а потім після цього перемістіть квадрати «швидкості» по цьому шляху.
Mooing Duck

Відповіді:


33

Підйом і прогалини - це лише різні функції витрат. Для одиниці, яка може стрибнути, розрив має нормальну (?) Вартість, тоді як для одиниці, що не стрибає, вона має довільно високу вартість. Скелелазіння коштує додатково, як і складний ландшафт тощо. Алгоритм A * добре впорається з функціями витрат, тому якщо ваша реалізація вже не робить цього, просто google про те, як реалізувати A * з функцією витрат.

Сказавши це, однак, я не думаю, що A * є особливо хорошим підходом для тактичної RPG. Або точніше, це не повна історія. Ви не хочете, щоб ваші підрозділи сліпо блукали до своєї мети, ви хочете, щоб вони позиціонували себе, щоб використовувати прикриття, високі місця, що завгодно, одночасно просуваючись до кінцевої мети і прагнучи вбік противників і так далі. Тож тактичне значення кінцевої точки кожного кроку має величезне значення, а не лише наскільки близька до мети. Це вимагає більш поглибленого вирішення проблем, ніж просто простеження.


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

1
@DrMcCleod: Дійсно, і саме це я мав на увазі "Або точніше, це не повна історія". Ви, звичайно, можете використовувати A * або інший алгоритм, щоб виконати частину обробки, однак, я думаю, я би уникав таких підходів, як спробу уникнути спостережуваних вузлів через вартість руху, оскільки переміщення по місцевості, де підрозділ може потрапити під обстріл, краще оброблятись як розрахунок ризику / винагороди, ІМО.
Джек Едлі

13

Коли вам потрібні всі можливі варіанти руху одиниці, використовуйте Алгоритм Дікстра .

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

Отже, коли ви просто хочете найкоротший шлях від точки А до точки В, то A * - це хороший вибір. Але якщо ви хочете отримати всі можливі варіанти руху та найкоротший шлях до кожного з них, то Dijkstra - саме те, що ви хочете.

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

Щодо стрибків: вони можуть бути представлені як ще один край як в A *, так і в Dijkstra. Вони можуть мати таку саму вартість, як і для переходу звичайного краю або іншого. Ви також можете передати параметр "jump_height" алгоритму, який вказує алгоритму ігнорувати перехідні краї, які перевищують задану висоту.


9
Варто згадати тут, що A*насправді є лише узагальненням Дейкстри, тож якщо ви розумієте одне, не повинно бути занадто важким для розуміння іншого.
Кубік

8
Дійсно, якщо у вас є евристика, яка просто повертає 0 в алгоритмі A *, вітаємо! Ви щойно написали алгоритм Дейкстри.
Yann

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

1
Не впевнений, чому це так рекомендується. З прагматичної точки зору, Дайкстра застарів. Це викладається в КС з освітніх та історичних причин. Навіть A * застарілий для серйозної роботи; Карти Google, звичайно, не використовують його. Ви дивитесь варіанти ArcGraph сьогодні.
MSalters

2
@MSalters Dijkstra і A * - це ідеальні алгоритми для простих проблем, таких як тактичні RPG. Існує дуже вузький діапазон дійсних рухів (плитки) і дуже обмежена кількість способів переміщення по зазначених плитках (ортогональних, іноді діагональних) і зазвичай досить короткий максимальний шлях: SQRT (ArenaWidth² * ArenaHeight²). Обчислювально, різниця в сучасній машині незначна, тому що, ймовірно, досить малі значення, тож чому б турбуватися про більш складну реалізацію, коли простого достатньо для намічених тут цілей?
Valthek

2

Інші відповіді мають хорошу інформацію, тому обов'язково прочитайте їх.

Однак, щоб відповісти на ваше запитання: виходячи з псевдокоду, з яким ви пов’язані, у вас є якась функція, heuristic_cost_estimateде ви підраховуєте вартість від tileA до tileB (якщо вважати, що вони суміжні). Замість того, щоб використовувати квартиру (1) для цієї вартості, вам доведеться скоригувати її, щоб вона включала статистику плитки та одиницю статистики, а можливо, і крайню статистику.

Наприклад:

if (edge == JUMP && !unit.canJump()) 
    return INF;
if (tile.Type == Forest && unit.moveType == HORSE) 
    return 2;
//Other cases here
//-----
else 
    return 1;

Це дасть вам свій шлях. Тоді ви просто перемістіть одиницю по їх шляху, витрачаючи точки руху, і зупиніть їх, залишившись пунктами <edgeCost. Зауважте, що це може бути не зовсім оптимальним, якщо ви закінчите залишилися точки = 1, але це повинно бути досить добре для практичної RPG. Насправді ви хотіли б більше тактичних, як зазначив Джек Едлі!

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


1

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

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

Хороші симуляції свідомо не знаходять найкращого шляху. Набагато кращим алгоритмом може бути ієрархічне наведення маршрутів - якщо нічого іншого, намалювавши пряму лінію на карті та зробивши 4-5 точкових точок, а потім простежити шлях від однієї точки до іншої, враховуючи лише ваги вузлів, які є поки що відомо, і встановлення всіх інших вузлів важить на "байдужих". Крім того, ви можете запустити A * на більш грубій сітці спочатку, а потім знайти шлях від одного великого вузла до другого (але я здогадуюсь, що малювання лінії на карті теж добре).

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


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

@MSalters: Це може статися з методом "намалювати лінію" навіть після першої спроби, так. Навряд чи це траплятиметься не раз із ієрархічним методом грубої сітки (який, наприклад, займає середнє, середнє або навіть максимальне значення вартості вузлів всередині). Це майже точно, як грав би противник людини - уникайте великих перешкод, про які ви знаєте чи бачите здалеку як гірський ланцюг, інакше плануйте грубо здебільшого прямий шлях, і пробийте собі шлях. Якщо ви не знаєте, що є гора, ви йдете прямо до неї.
Деймон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.