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