Come determinare la gamma di possibili movimenti nel gioco di strategia a turni, a distanza?


11

Sto creando un gioco di strategia a turni bidimensionale usando c ++ e SFML-2.0. Il movimento è basato sulla distanza piuttosto che sulla griglia, con diversi pezzi a forma di triangolo che, in un dato turno, ciascuno può ruotare in posizione o spostarsi in avanti.

Il movimento funzionerà in modo tale che il giocatore scelga una posizione in cui spostare il pezzo, il che genera un potenziale percorso da prendere per il pezzo. Una volta che il giocatore conferma la sua decisione, il pezzo si sposterà lungo quel percorso nella posizione desiderata. I percorsi sono limitati da due fattori: la distanza, la distanza percorsa da un pezzo, tenendo conto di eventuali curve (quindi se c'è una curva, sarà la lunghezza lungo la curva e non direttamente da un punto all'altro); e l'angolo di sterzata, fino a che punto il pezzo può ruotare in qualsiasi punto (e fino a ogni punto) durante lo spostamento (ad esempio, da -30 a 30 gradi).

La mia domanda è, come devo fare per determinare la gamma di potenziali posizioni che il giocatore può selezionare per spostare il pezzo?

Non sono del tutto sicuro di quali equazioni e / o algoritmi usare qui. Il mio piano originale era estremamente complicato, al punto che era quasi impossibile da attuare, figuriamoci spiegare, e sono a questo punto totalmente perso con il progetto bloccato.

Come posso determinare il raggio di movimento di un'unità, tenendo conto del raggio di sterzata?

Ad esempio, nell'immagine qui sotto. Le linee rosse, blu e verdi sarebbero tutte della stessa lunghezza. Il cerchio viola indica il raggio di movimento che l'unità può muovere. (La forma è probabilmente imprecisa e le linee probabilmente non sono effettivamente della stessa lunghezza, ma hai l'idea)

inserisci qui la descrizione dell'immagine


Sarà ancora in grado di spostare la stessa distanza (totale). Quindi la domanda è davvero di capire "quanto va lontano?" / "Di quanto deve girare?" / " Dove deve girare?". Probabilmente devi iniziare a determinare il percorso regolare, quindi fare un passo indietro per gli angoli al di sopra di una certa quantità; notare che la distanza finale sarà più lunga in un percorso in linea retta (svolta più recente) rispetto alle curve.
Clockwork-Muse

Sì, la distanza percorsa è il principale fattore limitante. Il mio più grande ostacolo qui è che devo tener conto del fatto che il pezzo può girare e continuare a girare, in qualsiasi momento possa raggiungere, purché abbia ancora la distanza disponibile.
sfphilli,

Cosa vuoi dire, il raggio d'azione di un'unità? Intendi i punti in cui può spostarsi? Quanto conosci l'algebra lineare (vettori)?
BlueRaja - Danny Pflughoeft,

1
Quale scenario di vita reale stai cercando di modellare? Il tuo problema è troppo vago per quanto riguarda i requisiti, con conseguente proposta di troppi approcci di soluzione. Esistono approcci ben noti per (praticamente) ogni problema specifico in quest'area, ma tutti indovinano quale di questi molti problemi si stanno effettivamente affrontando.
Pieter Geerkens,

1
@PieterGeerkens Suppongo che OP non stia richiedendo codice, sta richiedendo un algoritmo. E hanno fornito abbastanza dettagli sullo scenario da poter ragionevolmente concepire un algoritmo. Questo è comune e accettabile.
MichaelHouse

Risposte:


4

Genera un campo di flusso o distanza, usando Dijsktra's.

In sostanza, riempire una griglia usando l'algoritmo Dijkstra senza destinazione (probabilmente un nome diverso per quello; non lo so). Basta prendere ciascun nodo aperto, calcolare i vicini raggiungibili, spingerli nell'elenco aperto, impostarli nell'elenco chiuso, aggiornare il percorso "successivo" del nodo padre come appropriato, ecc. Quando si determina il costo per raggiungere un nuovo nodo, considerare le limitazioni di svolta.

Il risultato sarà ora che hai una rete di tutti i tuoi nodi su come tornare all'inizio. I nodi che non possono essere raggiunti non saranno stati toccati dal primo passo. I nodi che possono essere raggiunti avranno un "nodo successivo lungo il percorso migliore possibile verso il genitore" calcolato in modo da poter sia evidenziare tutti i nodi e quindi utilizzare queste informazioni per mostrare o eseguire il percorso di movimento mentre l'utente passa o fa clic sulle aree evidenziate.


Non esattamente come spiegherei il concetto, o come lo implementerei, ma sicuramente l'approccio giusto.
Pieter Geerkens,

La mia comprensione dell'algoritmo, così com'è, è che il nodo-traversal deve essere indipendente dal percorso. Quindi, per raggiungere questo obiettivo, dovresti aggiungere un altro grado di libertà (un altro asse su cui creare i tuoi nodi) dedicato al rivestimento. In altre parole, avresti un nodo per ogni combinazione di X, Y, potenzialmente Z e fronte differenti. Altrimenti, trovare il percorso più breve per entrare in un nodo non distingue tra i diversi aspetti quando lo si lascia. È corretto? In tal caso, questo metodo è forse troppo intenso?
TASagent,

@TASagent: buon punto, non ci ho pensato del tutto. L'algoritmo quindi è forse un po 'fuori ma l'approccio dovrebbe funzionare.
Sean Middleditch,

@PieterGeerkens: sono d'accordo che sia una cattiva spiegazione. Dovresti creare una tua risposta che spieghi tutto meglio.
Sean Middleditch,

Sembra che sia abbastanza vicino a ciò di cui ho bisogno, ma devo ammettere di non aver mai sentito parlare di quell'algoritmo e quindi non so come generalizzarlo a ciò di cui ho bisogno. Ti capita di avere un link a qualche buona informazione o tutorial su di esso?
sfphilli,

4

Una soluzione di forza bruta sarebbe:

  1. Crea un cerchio di vertici attorno all'unità, con l'unità al centro. Il raggio del cerchio è la massima distanza di movimento. La densità dei vertici può cambiare in base alla precisione del risultato finale.
  2. Per ciascuna posizione del vertice, simulare il movimento dell'unità sterzando verso quella posizione. Questo viene fatto in un ciclo stretto senza rendering.
  3. Quando viene raggiunta la distanza massima nella simulazione dello sterzo, spostare il vertice sul punto dell'unità simulata. Questo punto è il più vicino che l'unità potrebbe raggiungere a quel vertice prima della fine del turno in corso. Ciò ha l'effetto di restringere il cerchio alle dimensioni del movimento effettivo.
  4. Usa quei vertici, insieme a un vertice centrato sull'unità per creare un cerchio renderizzato per disegnare le possibili distanze di movimento.

inserisci qui la descrizione dell'immagine

Quindi, a partire dal cerchio blu, elaboreresti i tuoi percorsi, finendo con il cerchio viola. Quindi è possibile utilizzare quei punti con un punto centrale sull'unità per creare i triangoli rossi richiesti per visualizzare la forma. (Basta fare quell'immagine mi fa capire che quella forma non è corretta, ma sarà interessante vedere cosa è effettivamente corretto)


3

Espanderò la soluzione di Sean in una risposta separata, in quanto rappresenta un approccio diverso da quello che stavo inizialmente proponendo.

Questa soluzione rappresenta probabilmente il metodo più accessibile. Richiede il partizionamento dell'ambiente in nodi. Sì, questo sta reintroducendo un approccio basato sulla griglia, ma può essere reso relativamente fine o utilizzato per un ampio pathfinding con posizionamento più fine gestito all'interno del nodo. Più la struttura del nodo è grossolana, più veloce è il pathfinding.

Il grosso problema qui è che hai effettivamente a che fare con il rivestimento delle navi, quindi molte soluzioni tradizionali di rilevamento dei percorsi non possono essere utilizzate senza modifiche. Questi di solito sono indipendenti dal percorso, in quanto non si preoccupano di come sei arrivato al nodo in cui ti trovi. Funziona bene quando l'accelerazione, la decelerazione e la rotazione sono istantanee e libere. Purtroppo per te girare non è gratuito. Tuttavia, poiché in questa semplificazione esiste davvero un'informazione aggiuntiva che viene eliminata, possiamo codificarla come un'altra variabile. In fisica, questo sarebbe noto come spazio-fase.

Supponendo 2 dimensioni per ora, puoi estrapolare 3:

Di solito, è necessario un nodo per ogni posizione di coordinate discreta consentita. Per esempio:

(0,0) - (1,0) - (2,0)
  | \  /  |  \  / |
(0,1) - (1,1) - (2,1)

Ecc. Costruiresti un nodegrafo di punti adiacenti e li collegheresti per adiacenza spaziale. Quindi useresti l'algoritmo di Dijkstra, uccidendo i nodi che superano il valore di movimento consentito per il turno, fino a quando non ci sono nodi viventi inesplorati che rimangono connessi ai nodi esplorati. Ogni nodo tiene traccia della distanza minima necessaria per raggiungerlo.

Per espandere questo metodo in modo che sia utilizzabile con Rotation, immagina questo stesso nodegrafo in 3 dimensioni. La direzione Z corrisponde alla rotazione / orientamento ed è ciclica, il che significa che se continui a viaggiare nella direzione + Z torni a dove hai iniziato. Ora, i nodi corrispondenti alle posizioni adiacenti sono collegati solo attraverso il rivestimento corrispondente a quella direzione. Si scorre i nodi collegati ai nodi già esplorati come al solito. Consiglierei di limitare a N, NE, E, SE, S, SW, W, NW in questo schema.

Questa soluzione può dirti tutte le regioni accessibili dello spazio, nonché il percorso migliore per arrivarci, quanta rotazione hai quando arrivi lì e tutti gli orientamenti che potresti avere quando arrivi lì.

Quindi, quando esegui effettivamente il percorso, sei libero di interpolare / spline cubiche per renderlo più autentico.


1
Questo è eccellente Dovrò fare una piccola ricerca sull'algoritmo e sperimentarlo nel mio gioco, ma questo mi sembra davvero perfetto, soprattutto perché posso generalizzarlo in alcune altre parti importanti del gioco.
sfphilli,

1

Sembra che potresti dover prima decidere su come esattamente ti piacerebbe che l'accensione funzionasse. Opzioni come:

  • Se si muovono all'interno del cono, prima ruota, quindi inizia a muoversi. Questa è la soluzione più semplice da implementare e per cui effettuare il percorso. È anche meno interessante, quindi non vorrei usarlo.

  • Rotazione continua durante lo spostamento, fino a un totale di 45 gradi. Questo è molto più complicato e, si spera, quello che stai cercando. L'integrazione numerica sul percorso utilizzando un timestep fisso è probabilmente il modo più semplice per avvicinarsi a questo. Il tuo cono sarà limitato dalla rotazione massima (+ X gradi ogni passo) e minima (-X gradi ogni passo).

Il modo migliore per attraversare lo spazio con il secondo di questi requisiti dipende in gran parte dall'ambiente in cui si sposteranno. Se ci sono molti ostacoli da attraversare, allora le cose possono diventare davvero complicate e molto costose. Tuttavia, in caso contrario, è possibile caricare in anticipo (e persino diminuire) la rotazione per finire nella posizione desiderata.

Ho la sensazione di aver coperto solo parzialmente gli argomenti di cui hai avuto una domanda, quindi sentiti libero di aggiungere altro nei commenti e posso espandere la discussione.


Voglio assolutamente usare la seconda opzione, di alzare (ad esempio) di 45 gradi in qualsiasi punto, e potenzialmente in ogni punto, lungo un percorso. Ci saranno anche ostacoli, ognuno più grande dei pezzi (pensa a rocce giganti). Il modo in cui inizialmente pensavo a questo era generare un cono di possibili endpoint, quindi per ciascuno di quegli endpoint generare un nuovo cono, e così via per ogni possibile posizione fino a raggiungere la massima distanza percorsa. Detto questo, non sono del tutto sicuro di come implementarlo senza una folle eccessiva complicazione.
sfphilli,

Hmmm, sembra che non fossi / sono un po 'poco chiaro su alcuni dettagli. Guardando indietro alla domanda, vedo che hai specificato "a turni" e che le unità possono "ruotare o muoversi" nel loro turno. Vuol dire, quindi, che il giocatore organizza le proprie azioni con molti turni in anticipo, e tu vuoi fare il pathfinding mentre si muovono? Qualche ulteriore chiarimento su come dovrebbe funzionare il movimento sarebbe utile.
TASagent,

No, ciò che intendevo dire era che in un dato turno il giocatore può ruotare il proprio pezzo in posizione, per quanto lo desideri, oppure può muoversi nella direzione in cui sta già guardando. Se si muovono, possono percorrere una determinata distanza lungo un percorso e possono girare o virare fino a un angolo particolare (quindi ad esempio da -45 a 45 gradi) mentre si muovono. Immagina quindi che un percorso scelto implichi una curva per spostarsi a sinistra o a destra. Il percorso sarebbe determinato dal giocatore che sceglie un punto in cui vuole spostarsi, entro l'intervallo di possibili punti che ho difficoltà a determinare.
sfphilli,

Ok, quindi in realtà sembra che, sfortunatamente, le tue caratteristiche desiderate siano forse troppo restrittive per l'algoritmo Dijkstra di cui stiamo parlando sopra: - \. Possibilmente. Disegnerò alcune cose per questo più tardi quando torno a casa.
TASagent,

Potresti voler modificare alcune di queste informazioni che hai raccolto per chiarire il problema nella domanda originale, in modo che le persone che vengono dopo possano iniziare con maggiori informazioni.
TASagent,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.