Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ws2425:landkarten

Dies ist eine alte Version des Dokuments!


Landkartenprojekt

Mitglieder: Alex, Magdalena L., Sebastian

Protokolle

Kurze Beschreibung

Modellierungen einer 2-dimensionalen Landkarten, mögliche Ziele wären dann noch die Modelierung von Strukturen auf der Karte wie zum Beispiel: Wälder, Berge, Häuser und weiteres.
Informationen zu Höhenunterschieden, Flussläufen… sollen dabei generiert und zu einer möglichst realistischen Karte verarbeitet werden, Wälder… sollen danach in die Karte integreirt werden und dabei von den Höhen- und Flussstrukturen abhängen.

Projektplanung

Ziele
  • Generierung von Höhen
  • Generierung von Flüssen
  • Visualisierung einer ästhetischen Karte und einer passenden Legende
  • Wälder und Städte an passenden stellen Generieren und darstellen
  • Strukturen an wählbare Umgegungen/Biome anpassen
  • Wenn noch Zeit bleibet Code so überarbeiten, dass das Ergebnis möglichst realistisch wird
Aufgabenverteilung

Dokumentation

Unser Projekt soll möglichst realitätsnahe Landschaften generieren, dazu können Erosionssimulationen gehören, aber auch die Auseinendersetzung damit, wie ein klassischer Flusslauf aussieht und wie dieser im Code umgesetzt werden kann. All das können wir aber erst umsetzen, wenn wir eine sonst weitest gehend Funktionierende Grundlage haben, die mehr Zeit in Anspruch nimmt, als wir es erwartet hatten.

Projektverlauf

Funktionsweise

Den Code haben wir auf mehrere Dokumente verteilt, die je eine der unten genauer beschriebenen Klassen enthalten. So ist der Code gut lesbar und leichter zu verstehen.

Heightmap

Um eine Höhen zu generieren haben wir Perlin-Noise genutzt. Dabei wird für Stellen im regelmäßigem Abstand eine Steigung generiert, diese Steigungen bzw. Vektoren werden dann mit einer Funktion so verbunden, dass jese Stelle der Karte eine Höhe zugewiesen bekommt. Diese Höhen haben wir dann auf Höhen von einem Minimum von 0.0 bis zu einem Maximum von 1.0 normalisiert.
Einen Code für ein Eindimensionales Perlin-Noise haben wir selbst geschrieben, danach haben wir gemerkt, dass es dafür ein Pythonpaket gibt, das wir von da an für unsere Karte verwendet haben.
Um die Höhen darzu stellen haben wir mit

measure.find_contours()

Höhenlinien berechnet. So werden Contouren zurückgegeben, die so verteilt sind, das sie an den Stellen liegen, an denen sie ungefähr liegen müssten, wenn eine tatsächlich abgerundete Karte vorläge. Die berechneten Conturen visualisieren wir als pyglet Line.
Die Bergspitzen werden gefunden, indem die Höhe von jedem Pixel mit der, der umligenden verglichen wird. Liegt der geprüfte Pixel höher als die umligenden, wird er in einer Liste gespeichert. Anschließend wird geprüft, wie nah die Punkte bei einander liegen. Ist der abstand kleiner als 5 wird der Punkt aus der Liste gelöscht. Dargestellt werden die Bergspitzen als pyglet Circle.

Water

Als Wasserelemente wollten wir einerseits einen Meeresspiegel, andererseits Flüsse und Seen kreiren.
Als Meeresspiegel haben wir die Höhe 0.3 gewählt. Für die Konturlinien wird wieder measure.find_contours() verwendet.
In der Visualisierungs-Funktion kann nun die Anzahl der Wasserquellen festgelegt werden. Nun werden für diese Anzahl an Punkten ein zufälliger Punkt auf dem Grid als Flussquelle festgelegt. Da Flüsse meist in Gebirgen entstehen, haben wir hier festgelegt, dass die Quellen je eine Höhe von über 0.5 besitzen muss.
Für jeden dieser Ursprungspunkte wird nun ein Fluss erstellt. In der Funktion

Water.flussverlauf_erstellen()

wird immer der niedrigste Nachbar eines Punktes gewählt und zum nächsten Teil des Flußverlaufs gemacht. Dies wird so lange gemacht, bis kein Nachbar des momentanen Punktes höher als dieser ist. Dieser Punkt ist dann das Ende des Flusses und an diesem Punkt entsteht dann ein potenzieller See.
Zur Visualisierung des Flusses wird dann das in Pyglet enthaltene BezierCurve shape verwendet, um der natürlichen Form eines Flusses näher zu kommen.
Um die Höhe des Sees zu bestimmen wird die Funktion

Water.level_bestimmen()

verwendet. Die Funktion sucht immer den Punkt mit der niedrigsten Steigung, welcher noch nicht 'gechecked' wurde und sich somit die niedrigste Stelle wo der See übertreten und wieder in einen Fluss münden würde.
Auf dieser Höhe wird dann die Konturlinie gezeichnet. Für jede Kontur auf diesem Level wird der durchschnittliche und der minimale Abstand zu der Mitte des Sees berechnet. Wenn die Kontur mit dem niedrigsten Abstand zu der Mitte des Sees (Endpunkt des Flussverlaufs) nicht mit der Kontur des niedrigsten durchschnittlichen Abstandes übereinstimmt, wird geguckt ob die Kontur sich am Rande des Grids befindet, weil das die Werte der Abstände 'verfälschen' kann. Diese Funktion entscheidet sich leider nicht immer für die richtige Kontur, aber liegt schätzungsweise zu in 80% der Fälle richtig.
Wenn man nicht auf die Größe der Seen achtet, bekommt man hin und wieder leider sehr große Seen, die nicht so gut auf der Karte aussehen. Deshalb wollten wir diese Seen vermeiden und haben Seen, dessen Umriss (Liste aus Punkten) größer als 64 ist, nicht zugelassen. Wir haben hierbei die Länge 64 gewählt, weil es auch die Länge ist, die das Polygon Shape in Pyglet maximal haben kann, welches wir zu der Visualisierung der Seen verwenden.
Falls ein See Umriss jetzt länger als 64 ist, wird solange von der Höhe des Sees 0.01 abgezogen, bis die Länge des Sees unter 64 ist.
Was wir leider nicht mehr in der Zeit fertigstellen konnten war, dass aus den Seen dann wieder Flüsse entstehen. Das Problem, welches wir am Ende hatten war, dass der neu entstehende Fluss in vielen Fällen einfach wieder zurpck in die Mitte des Sees floß, anstatt weiter zu fließen.

Visualisierung

Fazit

Quellen/Literatur

Erste Inspiration
Perlin-Noise-Paket hier

ws2425/landkarten.1741716406.txt.gz · Zuletzt geändert: 2025/03/11 19:06 von sebastianstannat