In un gioco con piattaforma 2D, come garantire che il giocatore si muova senza intoppi su un terreno in pendenza?


18

Sto sviluppando un motore fisico per un gioco con piattaforma 2D. Sto usando il teorema dell'asse di separazione per il rilevamento delle collisioni. La superficie del terreno è costruita da scatole di delimitazione orientate, con il giocatore come una scatola di delimitazione allineata sull'asse. (In particolare, sto usando l'algoritmo dal libro "Realtime Collision Detection" che esegue il rilevamento di collisioni con sweep per OBB usando SAT). Sto usando un coefficiente di restituzione abbastanza piccolo (vicino allo zero) nella risposta alla collisione, per garantire che gli oggetti dinamici non penetrino nell'ambiente.

Il motore funziona principalmente bene, è solo che sono preoccupato per alcuni casi limite che potrebbero verificarsi. Ad esempio, nel diagramma, A, B e C sono la superficie del terreno. Il giocatore si sta dirigendo a sinistra lungo la B verso A. Mi sembra che a causa di inesattezze, la casella del giocatore potrebbe essere leggermente al di sotto della casella B mentre continua su e sinistra. Quando raggiunge A, quindi, l'angolo in basso a sinistra del giocatore potrebbe quindi scontrarsi con il lato destro di A, il che sarebbe indesiderabile (poiché l'intenzione è che il giocatore si muova senza intoppi sopra la parte superiore di A). Sembra che un simile problema possa verificarsi quando il giocatore si trova in cima alla casella C, spostandosi a sinistra verso B - il punto più estremo di B potrebbe scontrarsi con il lato sinistro del giocatore, invece che l'angolo in basso a sinistra del giocatore scivola verso l'alto e a sinistra sopra B.

Box2D sembra gestire questo problema archiviando le informazioni di connettività per le sue forme dei bordi, ma non sono davvero sicuro di come usi queste informazioni per risolvere il problema, e dopo aver visto il codice non capisco davvero cosa sta facendo.

Ogni suggerimento sarà molto apprezzato.


Un motore di fisica generale è ottimo per effetti e scatole che cadono e tutto il resto, ma non per la fisica dei personaggi, come indicato nella sezione delle risposte. Prendi in considerazione la possibilità di scrivere una fisica "statica" per il tuo personaggio, così puoi avere il controllo al 100% e utilizzare dinamiche adeguatamente simulate per il resto.
Domi,

Risposte:


14

Platforming e fisica

Questi casi limite sono numerosi. I bravi platform divertenti non si comportano in alcun modo in modo fisicamente accurato e il controllo e il comportamento che i giocatori si aspettano dopo anni di platform "perfetti" come Mario sono incredibilmente difficili da implementare con tecniche generali come quelle ottenute con Box2D o altri motori fisici. La maggior parte dei bravi platform non utilizza alcun tipo di fisica generica o risposta alle collisioni nei controller dei suoi giocatori.

Genera scafi

Per quanto riguarda la tua domanda specifica, la soluzione migliore è smettere di usare le scatole come base. Utilizzare una serie di segmenti di linea collegati (uno scafo). Ciò consente al motore di rilevamento delle collisioni di concentrarsi solo sulle superfici effettivamente percorribili e di non guardare al bordo "falso" che esiste tra AB e BC. Questo è ciò che fa Box2D, in effetti. Le forme vengono utilizzate per generare le superfici esterne, che sono collegate tra loro per formare uno scafo.

Ne hai bisogno anche nei giochi basati su tessere o in situazioni in cui hai due oggetti AABB accanto ad altri che fungono da pavimento. Il motore di collisione raccoglierà quei bordi verticali e farà in modo che il giocatore li afferri. Ci sono hack che possono aiutare, ma non eliminare il problema. La soluzione è avere un solo segmento di linea che rappresenti la superficie anziché un riquadro 2D completo.

È possibile generare gli scafi nel caso generico tagliando i poligoni l'uno contro l'altro e unendo i punti di clip in un elenco di bordi.

Superfici inclinate

Poiché il tuo esempio include una pendenza e stai menzionando la restituzione e altre proprietà fisiche, ti segnalerò alcuni altri problemi che noterai presto, il che illustra ulteriormente perché il rilevamento e la risposta di collisioni generici non funzionano bene per i platform. Per prima cosa, prova a stare in piedi sulla piattaforma ad angolo, salta su e poi atterra. Probabilmente noterai che il personaggio "scivolerà" un po 'durante l'atterraggio. Il problema è che il contatto normale che stai generando di solito verrà indicato dalla superficie inclinata. Quindi, quando si risolve la collisione, il giocatore viene espulso in quella direzione. Anche se il personaggio stava cadendo verso il basso, verrà spinto verso l'alto e un po 'a destra durante l'atterraggio, risultando nella diapositiva. Questo può essere hackerato tenendo conto delle velocità relative,

Il secondo problema che noterai, che è molto più difficile da risolvere, è quello che succede quando provi a correre rapidamente giù da una rampa. Il giocatore "salterà" lungo la rampa. Questo è molto visibile anche nella maggior parte dei giochi AAA oggi. Non solo sembra sciocco, ma se il tuo gioco richiede che il giocatore sia messo a terra per saltare, rende difficile correre giù da una rampa e saltare a metà, perché il giocatore sta solo contattando la rampa durante una piccola porzione del il tempo trascorso scendendolo. Una soluzione più semplice consiste nel fare semplicemente alcuni lanci di raggio quando il giocatore si muove e agganciare la posizione del giocatore alla superficie più vicina (se è molto vicino al giocatore) se il giocatore non sta saltando ed era precedentemente a terra.

Potresti anche scoprire che il giocatore si lancia in aria quando corre su una rampa se provi a modellare velocità, attrito e restituzione sul giocatore come se fosse un normale corpo rigido. Il movimento del giocatore dovrebbe essere limitato al movimento orizzontale a meno che non cada / salti. Ovviamente, se giochi a platform più vecchi dell'età dell'oro, potresti notare che la velocità orizzontale del giocatore è spesso costante tra superfici orizzontali e inclinate. Questo deve essere preso in considerazione anche quando si cammina su / giù per le piste.

Ci saranno un certo numero di altri strani casi angolari in cui ti imbatterai anche tu. Se stai cercando di diventare un buon platform, è davvero meglio implementare un controller del giocatore platform separato dalla fisica e codificare il comportamento di movimento e controllo desiderato, piuttosto che fare affidamento sulla fisica generica e sull'algoritmo di risposta alle collisioni.


Grazie per la tua risposta. Avevo pensato di ridurre le scatole che rappresentano il terreno in linee, ma in realtà non penso che in sé risolverà il problema. Ad esempio, se le caselle di terra sono ora linee e se il giocatore è in piedi sulla linea C e viaggia a sinistra verso B, a causa di inesattezze è possibile che la casella del giocatore sia leggermente al di sotto della linea C. Quindi, il bordo sinistro della casella del giocatore potrebbe ancora scontrarsi con la linea B e causare quella collisione indesiderata,
Nick Kovac

a meno che non ci siano altri meccanismi per impedire che ciò accada. Non è il fatto che Box2D utilizzi le linee invece delle caselle che risolvono il problema, è che Box2D utilizza una forma a catena, che utilizza le informazioni di connettività tra i segmenti di linea per evitare che si verifichino collisioni. Il problema principale al momento è che non capisco bene i dettagli di come lo fa esattamente.
Nick Kovac,

Hai sollevato alcuni altri punti davvero positivi sui problemi relativi all'acquisizione di idee dai motori di fisica generica e alla loro applicazione ai giochi con piattaforma. Ho visto motori simili che implementano le idee che hai discusso (modificando la collisione normale per le pendenze e risucchiando il giocatore sulla pendenza), quindi almeno quei problemi sono abbastanza facilmente risolvibili. Il principale punto critico per me sono i casi complicati legati agli errori numerici.
Nick Kovac,

@Kovsa: ancora una volta, quegli errori particolari scompaiono quando ti sbarazzi dei bordi che non dovrebbero essere parte della collisione in primo luogo. Incatena i bordi per formare una forma ininterrotta. Durante la progettazione del tuo livello, ti consiglio anche di agganciare i vertici in modo da non avere piccole fessure nelle superfici. Non molto diverso dal modo in cui si progetta il livello in un editor mesh 3D.
Sean Middleditch il

Hmm ... Non credo di seguirlo. Nel mio diagramma, se incatenassi i bordi per creare una forma ininterrotta, otterrei una forma composta da tre segmenti di linea: la parte superiore delle caselle A, B e C, giusto? Anche se è una forma singola, avrei comunque bisogno di eseguire il rilevamento delle collisioni separatamente contro la linea A, quindi B, quindi C, no? A meno che non intendessi un algoritmo in grado di rilevare una collisione tra la scatola e questa forma combinata? Suppongo che non sarebbe SAT allora, dal momento che una serie di spigoli potrebbe essere concava?
Nick Kovac,

5

Penso che entrambi i problemi possano essere risolti trattando le tue scatole, ai fini della risposta alla collisione, come se avessero angoli arrotondati (di un raggio simile al tuo errore numerico). Ciò renderà più liscia la superficie combinata effettiva degli angoli della riunione tra A e B e B e C.

Pertanto, se il GIOCATORE che si sposta a sinistra colpisce l'angolo di A, la collisione normale sarebbe diagonale anziché puramente verso destra, consentendo così la continuazione del movimento verso l'alto e verso sinistra.


Tuttavia, una soluzione più tipica, sulla revisione di ciò che so di fisica platform, è quella di rendere il giocatore una forma più arrotondata e lasciare da solo il terreno. In particolare, considera di trasformare la forma del giocatore in una capsula (cerchio allungato nel mezzo (2D) / sfera (3D)), quindi le tue normali di collisione saranno naturalmente quasi verticali, eliminando qualsiasi problema di cattura.

Dici che stai usando un algoritmo di collisione specifico per gli OBB, ma dovresti comunque essere in grado, dopo aver trovato una collisione OBB-OBB, di utilizzare un ulteriore test su una forma che è interamente all'interno dell'OBB.


Hmm, idea interessante ... come faresti per implementarla? Va in qualche modo contro la semplicità dell'uso delle caselle: (Sono d'accordo che sembra che dovrebbe essere un problema comune con una soluzione definitiva, ma non riesco a trovare alcuna copertura al riguardo davvero ... a parte ciò che viene fatto in Box2D. Ho pubblicato una domanda simile sul loro forum per avere maggiori informazioni.
Nick Kovac,

Non ho dettagli di implementazione, mi spiace, non sono un esperto di questo tipo di codice del motore fisico. Tuttavia, ho avuto un'idea migliore per una soluzione che non si basa su fattori fudge - vedi la mia modifica.
Kevin Reid,

1
Si noti che durante l'utilizzo di forme arrotondate funziona, è matematicamente più complesso e può comportare un comportamento non ottimale per i platform. I giocatori si aspettano di avere un controllo quasi perfetto dei pixel sui personaggi in piedi sulle sporgenze, ad esempio, le cui forme arrotondate renderanno più o meno impossibili e i personaggi scivoleranno fuori dalle sporgenze inaspettatamente.
Sean Middleditch,

Sporgenze: D'oh! OK, non è semplice come pensavo.
Kevin Reid,

Sì, dopo averci pensato, l'approccio della capsula sembra forse più adatto a un gioco 3D piuttosto che a un platform 2D. Avere il controllo perfetto dei pixel è sicuramente una priorità per me (come in tutti quei vecchi platform 2D). Ma ci deve essere una soluzione che consenta di utilizzare le scatole!
Nick Kovac,
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.