Procedural Terrain Generation Quantifizierung Spectral

Transcription

Procedural Terrain Generation Quantifizierung Spectral
Procedural Terrain Generation
Proseminar Game Design
Hager Simon
[email protected]
Sinn und Zweck dieser Ausarbeitung ist die automatisierte, also vom Benutzer unbeaufsichtigte,
Erstellung von 3D-Terrain für ein Echtzeitstrategiespiel. Dabei ist darauf zu achten dass die
Erstellung einigermaßen performant läuft, die Karten spielbar sind und optisch Ansprechend sind.
Spielbarkeit bedeutet in unserem Fall dass ein Großteil der Karte von Einheiten erreichbar ist, es
aber trotzdem steile Hänge gibt die den Level etwas aufteilen und die Wege einschränken, sowie
genug Bauplatz um Gebäude bauen zu können.
Zur Darstellung unseres Levels benützen wir eine Heightmap, da sie für Strategiespiele mehrere
Vorteile hat, wie einfache Berechnung von Wayfinding und Line-of-Sight-Abfragen.
Alle hier vorgestellten Methoden werden in dieser Form vom Spiel „Tribal Trouble“ [1] von
Oddlabs [2] eingesetzt, und vom Entwickler veröffentlicht [3], finden also durchaus Verwendung.
Quantifizierung
Da verschiedene Algorithmen gegeneinander abgewogen werden sollen, brauchen wir zuerst eine
Möglichkeit Spielbarkeit und Aussehen der Karte durch Zahlen auszudrücken.
Dazu führen wir zuerst eine 2te Heightmap S ein, auf der wir die Steigung jedes Punktes speichern.
Anschließend versuchen wir „Erosion“ in Mathematische Formeln zu packen, was wir erreichen
indem wir uns die Voraussetzungen die wir für unsere Karte brauchen ansehen:
– Viele flache Ebenen, mathematisch gesehen also einen niedrigen Mittelwert in unserer
Steigungskarte S
– Steile Hänge, was sich am leichtesten durch eine hohe Standardabweichung ausdrücken lässt.
Damit definieren wir uns eine Erosionspunktzahl ε, durch den Faktor der beiden Werte.
Als Spielbarkeit verwenden wir einen Faktor, der aussagt wie viele Prozent der Karte von Einheiten
erreichbar sind. Dazu erstellen wir eine Erreichbarkeitsmap, auf der alle Werte von S die größer
sind als T (Ein bestimmter Wert, den wir als das Maximum ansehen was eine Einheit an Steigung
bewältigen kann) 0 sind, der Rest 1. Damit erhalten wir eine Binärkarte die angibt wo sich eine 1x1
große Einheit überall bewegen kann. Da Einheiten größer sind als 1ne Einheit der Map, müssen
noch alle Bereiche wegfallen die eine n x n große Einheit nicht erreichen kann, sowie am Ende der
größte Zusammenhängende Bereich gewählt werden, da unsere Einheiten nicht in abgelegene Inseln
ohne Ausgang gelangen sollen.
Analog gehen wir beim Bauplatz vor, und erhalten am Ende eine „Spielbarkeitspunktzahl“ durch
Multiplizieren aller Faktoren.
Analog bedeutet hier dass Gebäude zwar viel größer sind als Einheiten, Schritt 3 (größten
Zusammenhängenden Bereich auswählen) brauchen wir aber nicht, da unsere Gebäude nicht
herumlaufen, sondern von Arbeitern gebaut werden Im Endeffekt benützen wir einfach das Ergebnis
des oberen Algorithmus, und lassen alle Bereiche wegfallen die zu klein sind um zu bauen.
Zusammenhängigkeit der Bereiche ist dabei irrelevant..
Spectral Synthesis
Kommen wir nun zur Erstellung unserer Karte. Wir beginnen mit der Simulation von 1/f Noise,
zufälliges natürliches Rauschen. Eine Möglichkeit dazu ist die Spectral Synthesis, in der
folgendermaßen vorgegangen wird:
Man generiert mehrere Heightmaps mit jeweils doppelter Auflösung und halber maximaler Höhe,
die anschließen einfach Übereinander gelegt werden. Die Heightmaps werden generiert indem
bestimmte Punkte auf ihnen Zufällig gesetzt werden und der Rest Interpoliert wird.
Hier lässt sich durch geeignete Interpolationsalgorithmen Rechenzeit sparen, Lineare ist für unsere
Karte völlig ausreichend, und ca. 5 mal so schnell wie die Kubische Methode.
Midpoint Displacement
Eine effektivere Methode 1/F Noise zu erzeugen ist Midpoint Displacement. Dabei werden die
Eckpunkte der Karte zufällig gesetzt, und danach der Mittelpunkt aus dem Mittelwert dieser Ecken,
modifiziert durch einen zufälligen Offset, berechnet. Anschließend wird das gleiche Verfahren
rekursiv auf die soeben entstandenen neuen 4 Vierecke angewendet, mit nur noch halb so großem
Offset, bis die gewünschte Auflösung der Karte erreicht ist.
Problem bei beiden Algorithmen ist, das Stochastisch ausgeglichene Karten entstehen, ohne scharfe
Kanten die Einheiten am Bewegen hindern würden. Dies sieht man auch an der Resultierenden
niedrigen Erosionspunktzahl von ~0.46
Voronoi Diagramme
Ein anderer Ansatz zum Erstellen von Karten basiert auf Voronoi Diagrammen. Dabei werden
zufällige Punkte auf der Karte gesetzt, sogenannte „Feature Points“, und der Rest der Karte durch
folgende Formel berechnet:
h = c1d1 + c2d2 + c3d3 + ... + cndn
wobei d1 der nächstgelegene FP ist, d2 der 2t-nächste usw., sowie cn beliebige Konstanten.
Damit erhalten wir zwar Spitze Berge mir hohen Steigungen, aber kaum flache Ebenen, was die
niedrige Erosion von 0.35 erklärt. Die Karte ist zudem auch Optisch sehr abschreckend.
Eine mögliche Verbesserung dieses Algorithmus ist es, bestimmte „Berge“ die durch das Voronoi
Diagramm entstanden sind wegfallen zu lassen (da diese Formel zu jedem FP einen Berg generiert,
was bedeutet, dass jeder Punkt der Karte zu einem Berg gehört), sowie die ganze Karte um einen
Offset zu reduzieren, und negative Werte auf 0 setzen, was zu flachen Ebenen zwischen den Hügeln
führt.
Da beide Ansätze der Erstellung der Karte nicht wirklich die Lösung für unser Problem sind,
brauchen wir eine weitere Idee. Die ist in diesem Fall ziemlich einfach, nämlich einfach das
kombinieren beider Ansätze.
Wir erstellen je eine Map mit Voronoi Diagrammen sowie Midpoint Displacement, und addieren sie
im Verhältnis von 1/3 Voronoi zu 2/3 Midpoint Displacement. Die dabei entstehenden, vom Voronoi
Diagramm übernommenen geraden Kanten, die nicht natürlich wirken, lassen sich durch das
anwenden eines „perturbation“ Filters beheben. Ein Link [4] zur genauen Umsetzung davon in
Tribal Trouble ist im Anhang. Dabei werden alle Punkte der Karte mittels stetiger Funktionen
verschoben, anschaulich gesprochen wird die Karte „verwischt“. Das wirkt sich auch auf die
Erosionspunktzahl aus, die liegt danach bei guten 0.67. Spielbar ist die Karte leider noch nicht, da
es kaum Bauplatz gibt (nur 0.2%) und auch nur 71% der Karte erreichbar für Einheiten sind,
folglich die niedrige Spielbarkeitspunktzahl von 0.001.
Diese erreichen wir durch Erosion, also die Simulation von natürlichen Wettereinflüssen, hier von
Sonne und Wasser.
Hydraulic Erosion
Die Simulation von Erosion durch Wasser ist leicht zu erklären: Wasser trägt Gestein ab, fließt nach
unten, und verdampft dort wieder.
Dazu erstellen wir eine 2te Heightmap w, die Wassermap. Auf ihr fügen wir jedem Punkt den
gleichen Wert an Wasser hinzu, und ziehen diesen Wert der Heightmap ab. Das Wasser löst das
Gestein also einfach auf. Dieses Wasser lassen wir danach nach unten fließen, unter
Berücksichtigung der Tatsache dass Wasser versucht immer eine flache Oberfläche zu bilden.
Anschließen wird aus dem Wasser wieder Gestein, also einfach die Wassermap zur Heightmap
wieder addieren. Falls wir diesen Algorithmus oft genug durchführen (ca. 200 mal) erhalten wir
auch ein Ansprechendes Ergebnis: Eine Erosionspunktzahl von 1.0, 82% der Karte sind betretbar,
sowie 15.7% Bauplatz. Der Grund dafür dass der Algorithmus nicht zum Einsatz kommt liegt in
seiner Laufzeit, er benötigt rund 30 Sekunden auf einem Standardrechner, was für unsre Zwecke
nicht ausreichend ist.
Thermal Erosion
Ein anderer Ansatz ist die Simulation von Erosion durch Sonne: Die Sonne lässt Abhänge brüchig
werden, worauf Gestein abbricht und nach unten rutscht. Angewendet sieht das so aus, das wir die
Steigung zwischen zwei Punkten auf einen Wert größer einem gewählten T überprüfen, und dann
solange Gestein abbrechen lassen, bis der Wert T erreicht ist. Dies führt zwar dazu dass wir hohe
Werte für Erreichbarkeit (98%) erhalten, aber kaum Bauplatz (0.2%), da ja keine lachen Ebenen
geschaffen werden, sondern nur die steilen Hänge auf die Steigung T abgeflacht werden. Sieht auch
dementsprechend sehr langweilig aus und erreicht nur nur eine Erosionspunktzahl von 0.62. Vorteil
dieses Algorithmus ist seine Laufzeit, eine Karte lässt sich problemlos in unter einer Sekunde
berechnen.
Kombination
Da beide Methoden für sich nicht brauchbar sind, versuchen wir nun die Vorteile von beiden zu
vereinen, das wären das Ergebnis der Hydraulic Erosion mit der Laufzeit der Thermal Erosion. Dies
geht ziemlich einfach indem wir nur die Thermal Erosion benützen, und die Bedingung: “Ebene ein
wenn Steigung größer T“ durch „Ebene ein wenn Steigung kleiner T“ ersetzen. Dies führt dazu dass
steile Hänge in Ruhe gelassen werden, während flache Hügel noch flacher werden. In Zahlen
ausgedrückt erhalten wir eine Erosionspunktzahl von 2.2, eine Erreichbarkeit von 90%, sowie sind
43% der Karte bebaubar. Auch Optisch ist die Karte am meisten Ansprechend.
Abschluss
Zwar ist es wie gerade ausgeführt durchaus möglich Karten für ein Echtzeitstrategiespiel
automatisiert zu erzeugen, was den Vorteil hätte dass man sich Aufwand beim Entwickeln eines
Spiels spart, sowie Speicherplatz, allerdings gibt es auch Nachteile auf die hier nicht eingegangen
wurde. So kann z.B. der obige Algorithmus die Spielbarkeit der Karte nicht garantieren, es kann
immer stochastische Ausrutscher geben. Eine Möglichkeit das zu verhinden wäre eine
Nachträgliche automatische Überprüfung der Karte nach obigen Faktoren, was aber zeitlich zu
aufwändig wäre. Im Fall von Tribal Trouble wird einfach davon ausgegangen dass ein Großteil
(99%) der erzeugten Karten Spielbar sind, wer eine Unspielbare erwischt, hat halt Pech gehabt.
Auch Balancing könnte Probleme geben, da nicht alle Spieler z.B. die gleiche Menge an Bauplatz
haben, oder Ressourcen unfair verteilt sind.
Dies alles führt dazu dass es kaum Spiele gibt, die ihre Levels automatisch nach solchen Methoden
erzeugen.
Referenzen
1. http://tribaltrouble.com/
2. http://www.oddlabs.com/
3. Jacob Olsen, Realtime Procedural Terrain Generation, 2004,
http://oddlabs.com/jo/terrain/Realtime%20Procedural%20Terrain%20Generation.pdf
4. http://oddlabs.com/forum/viewtopic.php?t=1156