Qual è il metodo più semplice per generare terreno liscio per un gioco 2d?


23

Qual è il metodo più semplice per generare terreno liscio per un gioco 2D come "Moon Buggy" o "Route 960"?

Ho ricevuto una risposta su stackoverflow.com per generare una serie di altezze casuali e sfocarle in seguito. Sì, va tutto bene. Ma sarebbe meglio dare alcuni punti e ottenere una curva regolare.

Risposte:


13

Un modo per raggiungere questo obiettivo è il seguente:

  • Crea un punto al centro dello schermo, con un'altezza casuale; ora hai due sezioni, una su ciascun lato di questo punto
  • Per ogni sezione, dividi in due posizionando un punto al centro di questa sezione, con un'altezza casuale (a distanza) tra i suoi due vicini
  • Ripeti n volte.

Ciò che accade è che i dettagli nello scenario diventano più fini con ogni iterazione.

Il modo in cui gestisci i casi limite dipende da te: potresti assumere punti a (0, altezza / 2) e (larghezza, altezza / 2) per esempio.

Spero che sia di aiuto!

EDIT: Ecco un'immagine che ho fatto per l'illustrazione:

terraingen

Questa è la stessa idea!


12

Supponendo che tu voglia un terreno veramente liscio, suggerirei di fare un passo indietro rispetto alle risposte basate sul rumore e capire da dove provengono. Un segnale di "rumore" è essenzialmente una somma di infiniti sinusoidi di ampiezze casuali, con l'ampiezza "media" a una data frequenza data da una funzione della frequenza f . Puoi ottenere la maggior parte delle definizioni comuni di "rumore" in questo modo. Ad esempio, il moto browniano ha un 1 / f ^ 2risposta in frequenza (ovvero, l'ampiezza media a una data frequenza è inversamente proporzionale al quadrato della frequenza): ciò significa che i punti vicini hanno una discreta correlazione tra loro, poiché le componenti ad alta frequenza del segnale sono pesantemente smorzata. Al contrario, il classico rumore frattale (spostamento del punto medio, rumore di Perlin, ecc.) Ha una risposta in frequenza 1 / f ; c'è più varianza tra i punti vicini, ma ancora un po 'di correlazione. Andando oltre, il rumore bianco ha una risposta in frequenza costante: non esiste alcuna correlazione tra i punti.

A che serve questo? Bene, puoi ottenere un segnale uniforme che ha ancora un aspetto un po 'rumoroso, semplicemente sommando una manciata di sinusoidi ma assicurandoti che abbiano un'ampiezza adeguata a qualsiasi data frequenza. Volete che le frequenze siano "casuali" in modo che nessuno di loro abbia un multiplo comune (altrimenti otterrete una componente periodica per la forma complessiva delle vostre colline), quindi suggerirei qualcosa come la seguente procedura (completa con esempio funzionante):

  1. Scegli 4 numeri (reali) a caso nell'intervallo [1..10] - queste saranno le frequenze delle tue onde sinusoidali. Ho "lanciato i dadi" su random.org e ho ottenuto: f 0 = 1,75, f 1 = 2,96, f 2 = 6,23 e f 3 = 8,07. Non c'è nulla di magico nel numero 4 (puoi usarne di più, ma usarne uno qualsiasi inizierà a rendere più evidenti le singole onde sinusoidali) o l'intervallo da 1 a 10 qui (è solo un modo per assicurarti che il tuo massimo e il più basso le frequenze non sono troppo distanti). Potrebbe avere senso scegliere una frequenza nell'intervallo [1..2] e il resto nell'intervallo [2..10] solo in modo da avere una sinusoide "dominante" nota.
  2. Per ognuna di queste quattro (o comunque molte) frequenze f i , scegli un'ampiezza a i da qualche parte nell'intervallo tra -C / f i e C / f i per qualche C costante . Il valore che scegli qui controlla l'ampiezza complessiva della tua onda - per comodità, ho scelto C = 1. Quindi avevo bisogno di numeri casuali nell'intervallo [-1 / 1.75 (= -0.571) .. 1 / 1.75 (= 0.571) ] e similmente negli intervalli [-0,338 .. 0,338], [-0,161 .. 0,161] e [-0,124 .. 0,124]. Rotolamento quattro volte ancora i dadi, ho un 0 = -0,143, un 1 = -0,180, un 2 = -0,012, ea 3 = 0,088. (Si noti che questo probabilmente non è il modo migliore per eseguire questo passaggio, poiché il valore massimo possibile della funzione è la somma delle ampiezze abs ( a 0 ) + abs ( a 1 ) + abs ( a 2 ) + abs ( un 3 ), potrebbe avere più senso di dividere ciascuna delle vostre quattro a I valori da questa somma una volta che li hai generato, e quindi moltiplicare ciascuno da C in modo che si può essere sicuri che il massimo precisa la funzione può raggiungere è C .)
  3. Scegli quattro "offset" o i , ciascuno nell'intervallo [0..2π] (0..6.28) - questi modificheranno i punti di partenza delle tue onde in modo che non inizino tutti a 0. Ho o 0 = 1,73, o 1 = 4,98, o 2 = 3,17 e o 3 = 4,63.
  4. 'Trama' la funzione f (x) = a 0 sin ( f 0 (kx + o 0 ) ) + a 1 sin ( f 0 (kx + o 1 ) ) + a 2 sin ( f 0 (kx + o 0 ) ) + a 3 sin ( f 0 (kx + o 0 ) ) - qui k è un'altra costante, una che controlla lo "stiramento" orizzontale delle tue funzioni. Dovrai capire di cosa si tratta per la tua applicazione; per comodità ho appena scelto k= 1, quindi la mia funzione generale è f (x) = -0.143 sin (1.75 ( x + 1.73)) - 0.180 sin (2.96 ( x +4.98)) - 0.012 sin (6.23 ( x +3.17)) + 0.088 sin (8.07 ( x +4.63)).

Ecco il risultato della mia corsa di esempio, come riportato in Wolfram Alpha: nota che corregge le dimensioni dei suoi grafici per scopi di visualizzazione, ma che dovresti avere un sacco di controllo sul tratto orizzontale e verticale del risultato tramite le costanti che ho menzionato sopra :

Sinusoide casuale semplice


10

L' algoritmo di spostamento del punto medio può generare un bellissimo terreno 2d.

esempio di terreno

C'è una leggera differenza tra lo spostamento del punto medio e ciò che suggerisce @tykel. L'algoritmo di Tykel suddivide l'orizzonte e sceglie una nuova altezza. Questo crea terreno in cui le cime sono uniformemente distanziate. Gli umani sono bravi a scegliere le regolarità, quindi il terreno generato sembrerà generato, non naturale.

La potenza del punto medio deriva dalla scelta del punto medio e dalla sua dislocazione lungo il normale di quella linea. Questo fa sì che i picchi possano variare su e giù e da un lato all'altro. Il terreno risultante è frattale e gli umani percepiscono i frattali come naturali.

Lo spostamento casuale dell'altezza potrebbe provocare un terreno in discesa se si immettessero altri due parametri (spostamento orizzontale, pendenza massima, ecc.). Ciò evidenzia un altro dei punti di forza di MPD; è molto semplice da sintonizzare. Due parametri, irregolarità e livello di dettaglio.


7

È possibile utilizzare le funzioni di rumore per generare altezze casuali. Il più semplice è il rumore di valore, che funziona esattamente come la tua descrizione: generi delle altezze di numeri interi casuali e poi interpoli le altezze tra di loro. Il metodo di interpolazione più utilizzato è la mappatura della curva a S cubica:

Supponiamo di avere altezza h0nel punto x0e altezza h1nel punto x1. Quindi, per ottenere l'altezza in qualsiasi punto x( x0<=x<=x1), si utilizza

t = (x-x0)/(x1-x0); // map to [0,1] range
t = t*t*(3 - 2*t); // map to cubic S-shaped curve
h = h0+t*h1;

Le altezze ottenute in questo modo saranno fluide, casuali, ma non molto interessanti. Per migliorare il tuo terreno, puoi usare il rumore frattale . Funziona così: supponi di aver generato una funzione h(x)che restituisce altezza a una determinata coordinata (usando il metodo sopra). Questa funzione ha una frequenza, determinata dalla frequenza delle altezze originali dell'interger. Per ricavarne un frattale, combini insieme funzioni con diverse frequenze:

fbm(x)=h(x) + 0.5*h(2*x) + 0.25*h(4*x) + 0.125*h(8*x);

In questo esempio, combino quattro frequenze: originale, doppia, 4 volte e 8 volte originale, con frequenze più alte con un peso inferiore. Teoricamente, i frattali vanno fino all'infinito, ma in pratica sono richiesti solo pochi termini. Il fbmnella formula sta per frazionario moto browniano - questo è il nome di questa funzione.

Questa è una tecnica potente. Puoi giocare con il moltiplicatore di frequenza, con pesi di frequenze diverse o aggiungere alcune funzioni per distorcere il rumore. Ad esempio, per ottenere una sensazione più "increspata", h(x)può essere modificato in 1-abs(h(x))(assumendo -1<=h(x)<=1)

Tuttavia, mentre tutto ciò è bello, questa tecnica ha un serio limite. Con un approccio basato sulla "linea di altezza", non puoi mai avere "sporgenze" del terreno. E immagino che siano una caratteristica molto bella da avere in un gioco simile a "Moon Buggy".

L'aggiunta di belle sporgenze è un compito difficile. Una cosa che mi viene in mente: puoi iniziare con una "linea di altezza" frattale e "tessellate" in una serie di spline o curve di Bezier. Quindi la linea del terreno sarà definita da diversi "punti chiave". Applicare un po 'di jitter a questi punti chiave: ciò comporterà una deformazione casuale del terreno, probabilmente formando alcune forme interessanti. Tuttavia, le autointersezioni del terreno potrebbero diventare un problema con questo approccio, specialmente con livelli di jitter elevati.


4

Esistono due metodi popolari per generare mappe di altezza del terreno.

Alcune risposte fornite qui sono già basate sull'algoritmo Diamond-square, ma conoscere il nome semplifica la ricerca di ulteriori informazioni. Il rumore di Perlin ha anche altri usi, quindi è bene controllarlo comunque.


L'OP parla di paesaggi 2D in stile mario, ma questi sono comunque buoni collegamenti.
tenpn

1

La mia idea sarebbe quella di creare una funzione di rumore levigato. Prima con un metodo intNoise (int) che restituisce un int "casuale", ma che dipende dall'input. Se si utilizza lo stesso input due volte, il risultato sarà lo stesso.

Quindi utilizzare un metodo di smoothing per creare un floatNoise (float) che utilizza i due numeri interi attorno all'input per creare un valore casuale.

Quindi utilizzare la posizione X come input e Y come output. Il risultato sarà una curva smussata ma con altezza casuale.

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.