Ich entwickle gerade ein 3D-Roguelike-Spiel, das in einer sehr großen Welt stattfinden wird. Die Welt wird durch einen prozeduralen Algorithmus generiert, der zur Laufzeit von einem externen Skript bereitgestellt wird. Um das Rendern zu beschleunigen und den Speicherbedarf zu minimieren, teile ich die Welt in Zonen ein. Eine Zone ist ein 2D-Rechteck mit einer maximalen Größe von 1024 x 1024 (muss kein Quadrat sein), das dynamisch zugewiesene (über ein einzelnes new
) Array von Tile
's enthält. Tile
ist so klein wie möglich definiert, um die Speichernutzung zu minimieren. Nur die Zonen, die auf dem Bildschirm oder in unmittelbarer Nachbarschaft sichtbar sind, befinden sich im Speicher. Der Rest wird je nach Bedarf aus der Festplattendatei geladen.
Das Problem, das ich habe, ist, dass der Kartengenerator nicht über das logische Zonenlayout Bescheid wissen muss, sodass er diese Art von Karte generieren kann (insbesondere für höhere Z-Ebenen wie Lofts in der Stadt):
Dies wäre viel zu viel Speicherverschwendung, um es in 1024 x 1024 einzuschließen. Es ist daher besser, es in kleinere Chuncks wie diese zu packen:
Zum Schluss die Frage: Wie kann ich die vom World Generator Script gelieferten Daten in die tatsächliche Weltstruktur im Speicher konvertieren?
Woran ich bisher gedacht habe:
- Das Skript hat eine Methode
SetTile(x, y, tileType)
, und die Welt wird automatisch alle 100 Zellen neu berechnet, damit die Zonen so effizient wie möglich sind. Dies erfordert VIELES Kopieren, Verschieben, Ändern der Größe usw. von Zonen - das ist ein sehr langsamer Vorgang, aber das Weltlayout wird in logischer Reihenfolge gehalten, sodass es beispielsweise einfacher wäre, Methoden wieGetTile(x, y)
im Skript zu implementieren - Das Skript verfügt über eine Methode, mit
SetTile(x, y, tileType)
der nur vorübergehend eine Kachel in std :: vector gespeichert wird. Nachdem alles erledigt ist, führt die Welt einen zweiten Durchgang aus, in dem Zonen berechnet werden. Dies ist viel schneller, hat aber einen Nachteil: Da Kacheln in keiner bestimmten Reihenfolge festgelegt sind, ist es wirklich schwierig, eineGetTile(x, y)
Methode im Skript zu haben. Vielleicht gibt es eine Lösung für diesen Nachteil, von der ich einfach keine Ahnung habe - esstd::map
ist viel zu langsam, um hier verwendet zu werden. - Wenn dies nicht außerhalb des Bildschirms möglich ist, besteht die Lösung möglicherweise darin, Zonen im Skript verfügbar zu machen und explizit zu erstellen (ich meine, in die Skript-API-
CreateZone()
Funktion und ähnliches zu integrieren). Ich möchte dies nicht, da Skripte für Endbenutzer und Benutzer verfügbar gemacht werden Ich möchte sie so robust wie möglich machen. - Vielleicht gibt es eine andere Lösung? Vielleicht kann ich die Weltgenerierung auf andere Weise organisieren (ich brauche noch Skripte, aber es kann ein Skript sein, das nur einen Teil der Welt generiert und dann eine Verbindung herstellt)?
Zusätzliche Dinge, die ich gerade angesprochen habe: Die ganze Welt kann zu groß sein, um sofort in Erinnerung zu bleiben. Das Problem wird also noch weiter verdreht - ich muss den Teil der Weltgeneration (im Skript) in Stufen aufteilen. Irgendwelche Vorschläge?
Was die Technologie betrifft: Ich verwende C ++ 03 'ohne Boost und AngelScript als Skriptsprache