Was ist die einfachste Methode, um ein glattes Terrain für ein 2D-Spiel zu erzeugen?

23

Was ist die einfachste Methode, um ein glattes Terrain für ein 2D-Spiel wie "Moon Buggy" oder "Route 960" zu erzeugen?

Ich habe auf stackoverflow.com eine Antwort bekommen, in der es darum ging, eine Reihe zufälliger Höhen zu generieren und diese später zu verwischen. Ja, das ist ganz okay. Aber es wäre besser, einige Punkte zu vergeben und eine glatte Kurve zu erhalten.

astropanisch
quelle

Antworten:

13

Eine Möglichkeit, dies zu erreichen, ist die folgende:

  • Erstellen Sie einen Punkt in der Mitte des Bildschirms mit einer zufälligen Höhe. Sie haben jetzt zwei Abschnitte, einen auf jeder Seite dieses Punktes
  • Teilen Sie für jeden Abschnitt in zwei Teile, indem Sie einen Punkt in der Mitte dieses Abschnitts platzieren, wobei zwischen seinen beiden Nachbarn eine (zufällige) Höhe liegt
  • Wiederholen Sie n-mal.

Was passiert, ist, dass die Details in der Szenerie mit jeder Iteration feiner werden.

Wie Sie mit Grenzfällen umgehen, bleibt Ihnen überlassen: Sie können beispielsweise Punkte bei (0, Höhe / 2) und (Breite, Höhe / 2) annehmen.

Hoffe das hilft!

EDIT: Hier ist ein Bild, das ich zur Veranschaulichung gemacht habe:

terraingen

Das ist die gleiche Idee!

Tim Kelsall
quelle
12

Angenommen, Sie möchten ein eigentlich glattes Terrain, dann würde ich vorschlagen, sich von den geräuschbasierten Antworten zurückzuziehen und zu verstehen, woher sie kommen. Ein "Rauschsignal" ist im wesentlichen eine Summe von unendlich vielen Sinuskurven mit zufälligen Amplituden, wobei die "durchschnittliche" Amplitude bei einer gegebenen Frequenz durch eine Funktion der Frequenz f gegeben ist . Auf diese Weise können Sie die meisten der gebräuchlichen 'Noise'-Definitionen erhalten. Zum Beispiel hat Brownsche Bewegung ein 1 / f ^ 2Frequenzgang (d. h. die durchschnittliche Amplitude bei einer bestimmten Frequenz ist umgekehrt proportional zum Quadrat der Frequenz): Dies bedeutet, dass nahegelegene Punkte eine gute Korrelation zueinander aufweisen, da die hochfrequenten Komponenten des Signals stark sind gedämpft. Im Gegensatz dazu hat das klassische fraktale Rauschen (Mittelpunktverschiebung, Perlin-Rauschen usw.) einen 1 / f- Frequenzgang; es gibt mehr Varianz zwischen nahegelegenen Punkten, aber immer noch einiges an Korrelation. Wenn Sie einen Schritt weiter gehen, hat weißes Rauschen einen konstanten Frequenzgang - es gibt überhaupt keine Korrelation zwischen Punkten.

Was nützt dir das? Nun, Sie können ein weiches Signal erhalten, das immer noch ein wenig verrauscht ist, indem Sie nur eine Handvoll Sinuskurven summieren und sicherstellen, dass sie bei den angegebenen Frequenzen eine angemessene Amplitude haben. Sie möchten, dass die Frequenzen "zufällig" sind, damit keine zwei von ihnen ein gemeinsames Vielfaches haben (andernfalls erhalten Sie eine periodische Komponente für die Gesamtform Ihrer Hügel). Daher würde ich Folgendes vorschlagen (vollständig) mit Arbeitsbeispiel):

  1. Wählen Sie zufällig 4 (reelle) Zahlen im Bereich [1..10] - dies sind die Frequenzen Ihrer Sinuswellen. Ich habe bei random.org gewürfelt und bekam: f 0 = 1,75, f 1 = 2,96, f 2 = 6,23 und f 3 = 8,07. Es ist nichts Magisches an der Zahl 4 (Sie können mehr verwenden, aber wenn Sie weniger verwenden, werden die einzelnen Sinuswellen offensichtlicher) oder dem Bereich 1 bis 10 hier (dies ist nur ein Weg, um sicherzustellen, dass Ihre höchsten und niedrigsten Werte erreicht werden Frequenzen sind nicht zu weit voneinander entfernt). Es kann sinnvoll sein, eine Frequenz im Bereich [1..2] und den Rest im Bereich [2..10] zu wählen, um eine bekannte dominante Sinuskurve zu erhalten.
  2. Für jede dieser vier (oder wie viele) Frequenzen f i , wählt eine Amplitude a i irgendwo im Bereich zwischen C / f i und C / f i für eine Konstante C . Der hier gewählte Wert steuert die Gesamtamplitude Ihrer Welle - der Einfachheit halber habe ich C = 1 gewählt. Dann benötigte ich Zufallszahlen im Bereich [-1 / 1,75 (= -0,571). 1 / 1,75 (= 0,571) ] und in ähnlicher Weise in den Bereichen [-0,338 ... 0,338], [-0,161 ... 0,161] und [-0,124 ... 0,124]. Ich würfelte noch einmal vier Mal und bekam eine 0 = -0,143, eine 1 = -0,180, eine 2 = -0,012 und einea 3 = 0,088. (Beachten Sie, dass dies wahrscheinlich nicht der beste Weg ist, um diesen Schritt durchzuführen. Der maximal mögliche Wert der Funktion ist die Summe der Amplituden abs ( a 0 ) + abs ( a 1 ) + abs ( a 2 ) + abs ( a 3 ) ist es möglicherweise sinnvoller, jeden Ihrer vier a i -Werte durch diese Summe zu dividieren und dann mit C zu multiplizieren, damit Sie sicher sein können, dass das genaue Maximum, das die Funktion erreichen kann, C ist .)
  3. Wählen Sie vier 'Offsets' o i , jeweils im Bereich [0..2π] (0..6.28) - diese optimieren die Startpunkte Ihrer Wellen so, dass sie nicht alle bei 0 beginnen. Ich habe o 0 = 1,73, o 1 = 4,98, O 2 = 3,17, und O 3 = 4,63.
  4. Zeichnen Sie die Funktion 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 ) ) - hier ist k eine andere Konstante, die die horizontale 'Dehnung' Ihrer Funktionen steuert. Sie müssen herausfinden, was dies für Ihre eigene Anwendung ist. der Einfachheit halber habe ich gerade k ausgewählt= 1, und so ist meine Gesamtfunktion 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)).

Hier ist das Ergebnis meines Beispiellaufs, wie in Wolfram Alpha dargestellt. Beachten Sie, dass die Größe der Diagramme für Anzeigezwecke festgelegt wird, dass Sie jedoch die horizontale und vertikale Ausdehnung des Ergebnisses über die oben genannten Konstanten genau steuern können sollten :

Einfache zufällige Sinuskurve

Steven Stadnicki
quelle
10

Der Algorithmus zur Verschiebung des Mittelpunkts kann ein wunderschönes 2D-Terrain erzeugen.

Geländebeispiel

Es gibt subtile Unterschiede zwischen der Verschiebung des Mittelpunkts und dem, was @tykel vorschlägt. Tykels Algorithmus unterteilt den Horizont und wählt eine neue Höhe. Dadurch entsteht ein Gelände, in dem die Spitzen gleichmäßig verteilt sind. Die Menschen sind großartig darin, Regelmäßigkeiten auszusuchen, sodass das generierte Terrain nicht natürlich, sondern generiert zu sein scheint.

Die Kraft des Mittelpunkts ergibt sich aus der Auswahl des Mittelpunkts und der Verschiebung entlang der Normalen dieser Linie. Dadurch variieren die Spitzen nach oben und unten sowie von Seite zu Seite. Das daraus resultierende Terrain ist fraktal und Menschen nehmen Fraktale als natürlich wahr.

Eine zufällige Höhenverschiebung kann zu einem Gefälle führen, wenn Sie einige weitere Parameter (horizontale Verschiebung, maximale Neigung usw.) eingeben. Dies unterstreicht eine weitere Stärke von MPD. es ist sehr einfach zu stimmen. Zwei Parameter, Unebenheit und Detailgenauigkeit.

deft_code
quelle
7

Sie können Rauschfunktionen verwenden, um zufällige Höhen zu erzeugen. Das einfachste davon ist das Wertrauschen, das genau wie Ihre Beschreibung funktioniert: Sie generieren zufällige ganzzahlige Höhen und interpolieren dann Höhen zwischen ihnen. Die am häufigsten verwendete Interpolationsmethode ist das kubische S-Kurven-Mapping:

Angenommen, Sie haben Höhe h0am Punkt x0und Höhe h1am Punkt x1. Dann verwenden Sie, um die Höhe an einem beliebigen Punkt x( x0<=x<=x1) zu erhalten

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;

Auf diese Weise erhaltene Höhen sind glatt, zufällig, aber nicht wirklich interessant. Um Ihr Terrain zu verbessern, können Sie fraktales Rauschen verwenden . Dies funktioniert folgendermaßen: Angenommen, Sie haben eine Funktion generiert h(x), die die Höhe an einer bestimmten Koordinate zurückgibt (mithilfe der obigen Methode). Diese Funktion hat eine Frequenz, die durch die Frequenz der ursprünglichen Zwischenhöhen bestimmt wird. Um daraus ein Fraktal zu machen, kombinieren Sie Funktionen mit mehreren Frequenzen:

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

In diesem Beispiel kombiniere ich vier Frequenzen - Original, Doppel, Vierfach und Achtfach - mit höheren Frequenzen bei geringerem Gewicht. Theoretisch reichen Fraktale bis ins Unendliche, in der Praxis sind jedoch nur wenige Begriffe erforderlich. Das fbmin der Formel steht für gebrochene Brownsche Bewegung - das ist der Name dieser Funktion.

Dies ist eine mächtige Technik. Sie können mit dem Frequenzvervielfacher oder mit Gewichten unterschiedlicher Frequenzen spielen oder einige Funktionen hinzufügen, um das Rauschen zu verzerren. Zum Beispiel, um mehr "Ridged" Gefühl zu bekommen, h(x)kann geändert werden 1-abs(h(x))(vorausgesetzt -1<=h(x)<=1)

Obwohl dies alles schön ist, hat diese Technik eine ernsthafte Einschränkung. Bei einem auf Höhenlinien basierenden Ansatz kann es niemals zu "Überhängen" im Gelände kommen. Und ich stelle mir vor, dass sie ein sehr schönes Feature in einem "Moon Buggy" -ähnlichen Spiel sind.

Schöne Überhänge hinzuzufügen ist eine schwierige Aufgabe. Eine Sache, an die ich denken kann - Sie können mit einer fraktalen "Höhenlinie" beginnen und sie in eine Reihe von Splines oder Bezier-Kurven "tessellieren". Dann wird die Geländelinie durch mehrere "Schlüsselpunkte" definiert. Wenden Sie etwas Jitter auf diese Schlüsselpunkte an - dies führt zu einer zufälligen Verformung des Geländes und möglicherweise zu interessanten Formen. Geländeselbstüberschneidungen könnten jedoch bei diesem Ansatz zu einem Problem werden, insbesondere bei hohen Jitterbeträgen.

Keine Ursache
quelle
4

Es gibt zwei beliebte Methoden zum Generieren von Geländehöhenkarten.

Einige der hier gegebenen Antworten basieren bereits auf dem Diamantquadrat-Algorithmus, aber die Kenntnis des Namens erleichtert die Suche nach weiteren Informationen. Perlin-Rauschen hat auch andere Verwendungszwecke, daher ist es gut, es trotzdem zu überprüfen.

msell
quelle
Das OP spricht von 2D-Landschaften im Mario-Stil, aber das sind immer noch gute Verbindungen.
Tenpn
1

Meine Idee wäre es, eine geglättete Rauschfunktion zu erstellen. Zuerst mit einer Methode intNoise (int), die ein "zufälliges" int zurückgibt, das aber von der Eingabe abhängt. Wenn Sie dieselbe Eingabe zweimal verwenden, ist das Ergebnis dasselbe.

Verwenden Sie dann eine Glättungsmethode, um ein floatNoise (float) zu erstellen, das die beiden Ganzzahlen um die Eingabe verwendet, um einen zufälligen Wert zu erstellen.

Verwenden Sie dann die X-Position als Eingabe und das Y als Ausgabe. Das Ergebnis ist eine geglättete Kurve mit zufälliger Höhe.

XGouchet
quelle