A * Taktik RPG'ler için Algoritma?


15

C ++ 'da gerçekten zayıf bir taktik RPG yazmakla uğraşıyorum. Şimdiye kadar bir 2D kiremit harita var ve sadece wikipedia pseudocode dayalı çalışan A * algoritması var .

Ancak gerçek taktik RPG'ler sadece düz bir düzlemde en iyi yolu bulup oraya taşınmazlar. Tipik olarak sınırlı hareket menzillerine sahiptirler ve yukarı veya aşağı tırmanmaları gerekir. Hiç Final Fantasy Tactics oynadıysanız bunlar Move and Jump istatistiklerinden etkilenir. Burası kaybolduğum yer. A * algoritmasını bir hedefe doğru en iyi yolu bulabilecek şekilde nasıl değiştirebilirim, ancak yol yalnızca çok fazla karo uzunluğunda mı? Yükseklik farklarını ve atlama istatistiklerini nasıl dikkate almalıyım? Bir boşluğun üstünden atlamayı nasıl uygularım?

Yardım ederse, şu anda haritam Vector of Tile nesneleriyle temsil ediliyor. Her döşemenin, haritanın kenarı boyunca veya bir döşemenin geçilemez olarak ayarlanmış olması gibi, hiçbir döşemenin olmaması durumunda nullptr olarak ayarlanan Kuzey, Güney, Doğu ve Batı döşemesine işaretçiler vardır.


5
Hareket aralığının neden bir sorun olduğunu bilmiyorum. En kısa yolu bulun ve ardından 'hız' karelerini bu yol boyunca hareket ettirin.
Mooing Duck

Yanıtlar:


33

Tırmanma ve boşluklar sadece farklı maliyet işlevleridir. Boşluğu atlayabilen birimin normal (?) Maliyeti, zıplamasız bir birim için keyfi olarak yüksek maliyeti vardır. Tırmanma maliyetleri, zorlu arazi, vb. Gibi ekstradır. A * algoritması maliyet fonksiyonlarını iyi idare edebilir, bu nedenle uygulamanız zaten yapmıyorsa, A * 'yı bir maliyet fonksiyonuyla nasıl uygulayacağınız için google.

Bununla birlikte, A * 'nın taktik bir RPG için özellikle iyi bir yaklaşım olduğunu düşünmüyorum. Ya da daha doğrusu, tam bir hikaye değil. Birimlerinizin hedeflerine körü körüne inmesini istemezsiniz, nihai hedefe doğru ilerlerken ve rakipleri kuşatmaya çalışırken, kendilerini örtüden, yüksek zeminden, istifade edecek şekilde konumlandırmalarını istersiniz. Dolayısıyla, her hareketin bitiş noktasının taktik değeri, sadece hedefin ne kadar yakın olduğu değil, büyük önem taşımaktadır. Bu, sadece yol bulmadan daha derinlemesine problem çözmeyi gerektirir.


10
'Taktik konumlandırma' hakkında iyi noktalar, ancak bu kararlar temel yol bulmadan daha yüksek bir seviyede uygulanabilir. Öte yandan, bir tür taktik analizör tarafından üretilen yol bulma algoritmasındaki düğümlere maliyet uygulamak iyi bir seçenek olabilir. Örneğin, düşmanın araziyle görüş hattı varsa, o arazideki düğümlerin çok yüksek bir maliyete sahip olmasını sağlayın.
DrMcCleod

1
@DrMcCleod: Gerçekten de, "Ya da daha doğrusu, tam bir hikaye değil" derdim. İşlemin bir kısmını yapmak için kesinlikle A * veya başka bir algoritma kullanıyor olabilirsiniz, ancak bir ünitenin ateşe girebileceği bir arazide hareket etmenin daha iyi bir şekilde ele alındığı için hareket maliyetiyle izlenen düğümlerden kaçınmaya çalışmak gibi yaklaşımlardan kaçınacağımı düşünüyorum. risk / ödül hesaplaması, IMO.
Jack Aidley

13

Bir birimin tüm olası hareket seçeneklerini istediğinizde, Dijkstra Algoritmasını kullanın .

A * ve Dijkstra arasındaki fark, Dijkstra'nın size belirli bir maliyetle ulaşılabilecek tüm olası en kısa yolları vermesidir ve bunların hiçbiri henüz hedefinize ulaşmazsa, maliyeti bir arttırır ve devam eder. Öte yandan A *, hedefe ulaşmak için iyi bir şansı olan rotaları hesaplamayı tercih eder.

Bu nedenle, A noktasından B noktasına en kısa yolu istediğinizde, A * iyi bir seçimdir. Ancak tüm olası hareket seçeneklerini ve her birine en kısa yolu istiyorsanız, Dijkstra tam olarak istediğiniz şeydir.

Tek yapmanız gereken Dijksta'nın Algoritmasını belirli bir hedef düğümü olmadan, ancak aşılmaması gereken maksimum maliyetle (ünitenin hareket aralığı) çalıştırmaktır. Bir düğüme seyahat ederken maksimum maliyeti aşarsa, ziyaret etmeyin. Algoritma, ziyaret edilmemiş kenarların olmaması nedeniyle sona erdiğinde, ziyaret edilen kümedeki her düğüm olası bir hedeftir ve düğümlerin önceki düğüm işaretçileri, ilk düğüme geri giden yolu temsil eden bağlantılı bir liste oluşturur.

Atlamalar ile ilgili olarak: Bunlar hem A * hem de Dijkstra'da başka bir kenar olarak temsil edilebilir. Normal bir kenardan veya farklı bir kenardan geçmekle aynı maliyete sahip olabilirler. Ayrıca algoritmaya, belirli bir yüksekliği aşan atlama kenarlarını yoksaymasını bildiren algoritmaya bir "jump_height" parametresi de iletebilirsiniz.


9
Burada bahsetmeye değer, A*bu gerçekten sadece Dijkstra'nın bir genellemesidir, bu yüzden birini anlarsanız diğerini anlamak çok zor olmamalıdır.
Kübik

8
Gerçekten de, A * algoritmanızda 0 döndüren bir buluşsal yönteminiz varsa, tebrikler! Dijkstra'nın algoritmasını yeni yazdınız.
Yann

9
"Dijkstra tüm mümkün olan en kısa yolları belirli bir maliyetle sağlandığım verir ve bunların hiçbiri henüz hedefinizi ulaşırsa, o tek maliyetini artırır ve devam ediyor" - çalıştığını ne de ne verir böyle de değildir. Aslında, ağırlıklı grafikler için en geniş ilk aramanın bir genellemesi. Tek bir kısa yol bulur. A * sadece bunun bir genellemesidir, çünkü mesafe sezgisel olarak mevcut olduğunuzda.
BlueRaja - Danny Pflughoeft

1
Bunun neden bu kadar yükseltildiğinden emin değilim. Pragmatik açıdan bakıldığında Dijkstra kullanılmıyor. CS'de eğitimsel ve tarihi nedenlerle öğretilir. A * bile ciddi işler için kullanılmaz; Google Haritalar kesinlikle kullanmaz. Bugünlerde ArcGraph varyantlarına bakıyorsunuz.
MSalters

2
@MSalters Dijkstra ve A * taktik RPG'ler gibi basit problemler için mükemmel ince algoritmalardır. Çok çeşitli geçerli hareketler (fayanslar) ve adı geçen fayanslar arasında hareket etmek için çok sınırlı bir yol vardır (dikey, bazen çapraz) ve genellikle oldukça kısa bir maksimum yol vardır: SQRT (ArenaWidth² * ArenaHeight²). Hesaplama olarak, modern makinede büyük olasılıkla oldukça küçük değerler için fark göz ardı edilebilir, bu yüzden burada basitçe açıklanan amaçlar için yeterli olduğunda basit bir uygulama neden daha karmaşık bir uygulama ile uğraşasınız ki?
Valthek

2

Diğer cevapların bazı iyi bilgileri var, bu yüzden bunları mutlaka okuyun.

Ancak, sorunuzu cevaplamak için: bağlandığınız sözde heuristic_cost_estimatekoduna dayanarak, tileA'dan tileB'ye (bitişik olduklarını varsayarak) maliyeti hesapladığınız bir tür işleve sahipsiniz. Bu maliyet için düz (1) kullanmak yerine, döşeme istatistiklerini ve birim istatistiklerini ve muhtemelen kenar istatistiklerini içerecek şekilde ayarlamanız gerekir.

Örneğin:

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

Bu size yolunuzu verecektir. Daha sonra, hareket noktalarını tüketirken birimi yol boyunca hareket ettirir ve kalan noktalar durursa. KalanPoints = 1 ile sonuçlanırsanız bunun tamamen uygun olmayabileceğini unutmayın, ancak bir uygulama RPG'si için yeterince iyi olmalıdır. Gerçekte, Jack Aidley'in işaret ettiği gibi daha taktik istersiniz!

Zorluk:
Daha gelişmiş olmak istiyorsanız, muhtemelen Djikstraları X mesafesi içindeki tüm alanları bulmak için önerildiği gibi kullanmak istersiniz, o zaman bu listedeki her alanı, hedefe, savunmaya yakınlık temelinde "en iyi" bir yer için değerlendirmek istersiniz. güç, bu konumdan saldırıya uğrayabilir veya saldırmayabilirsiniz, vb. Bu bilgilere dayanarak, bir döşeme seçer ve daha sonra Djikstras kullanarak hesapladığınız yolu izleyerek oraya giderdiniz.


1

Tırmanma ve boşluklar, sadece maliyeti değiştirdikleri için oldukça önemsizdir. Pathfinding (ve çoğu taktik AI), ziyaret edilecek tüm düğümlerin maliyetini toplamak ve bunu en aza indirmekle ilgilidir. Geçilmez bir uçurumun sonsuz (çok, çok yüksek) bir maliyeti olacak, eğimler normalden daha yüksek bir maliyete sahip olacak vb.

Ancak bu, gerçek düşmanlar genellikle çünkü değil en iyi çözüm genel optimal yolunu bulur yok optimum yolu bulmak. Son derece gerçekçi değil, bazen oyuncu için açık olan ve sinir bozucu bir noktaya (özellikle AI bu şekilde temelde yenilmez olduğunda, çünkü en uygun olanı seçtiğinde).

İyi simülasyonlar kasten en iyi yolu bulamaz. Çok daha iyi bir algoritma, hiyerarşik yol bulma yapmak olabilir - başka bir şey değilse, harita üzerinde düz bir çizgi çizip 4-5 yol noktası alarak, o zamana kadar sadece düğüm ağırlıklarını göz önünde bulundurarak bir yol noktasından diğerine yol bulma ve diğer tüm düğüm ağırlıklarının "kayıtsız" olarak ayarlanması. Alternatif olarak, önce kaba bir ızgarada A * çalıştırabilir ve daha sonra büyük bir düğümden diğerine pathfind (ancak harita üzerinde çizgi çizmenin de iyi olduğunu tahmin ediyorum).

Bu çok daha gerçekçi (ve grafik çok daha küçük olduğu için işlem gücünün bir kısmını da tüketiyor ). Evet, bu, bir birimin sadece uçuramayacağını öğrenmek için bir kayalığa doğru hareket ettiği anlamına gelebilir. Bu iyi, gerçek düşmanlara da oluyor. Bir dahaki sefere, bir daha olmayacak (çünkü şimdi sonsuz maliyet biliniyor).


1
Dikkat edin, "basit hiyerarşik yol bulma" oldukça aptal görünebilir. Doğrudan bir dağ sırtı yürüyüş birimleri almak, sadece orada yolun engellendiğini keşfetmek için. Daha sonra dağ geçidinden bir sonraki ara noktaya ve oradan varış yerlerine rota yaparlar - bu son ara nokta onlar için yoldan uzak olsa bile. Ön işleme, dağın önünden geçip oradan geçeceğini belirleyecektir. Ancak bunu yapmasanız bile, planlanan rotadan çok uzakta olduğunuzda, geri kalanını yeniden planlamanız gerekir.
MSalters

@ MSalters: Bu ilk denemeden sonra bile "çizgi çiz" yöntemi ile olabilir, evet. Kaba ızgara hiyerarşik yöntemiyle (örneğin ortalamayı veya medyanı, hatta içindeki düğümlerin maksimum maliyet değerini alır) bir kereden fazla gerçekleşmesi olası değildir. İnsan muhaliflerinin tam olarak nasıl oynayacağı tam olarak - bir dağ zinciri gibi uzaktan bildiğiniz veya görebileceğiniz büyük engellerden kaçının ve aksi takdirde kaba çoğunlukla düz bir rota planlayın ve yolunuzu ısırın. Bir dağ olduğunu bilmiyorsanız, doğrudan ona doğru yürüyorsunuz.
Damon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.