Ich möchte ein einfaches Spiel mit einer Blockwelt wie in Minecraft schreiben. Meine theoretische Frage ist, wie ich am besten mit diesen Blockinformationen während des Spielens umgehen kann. Meine erste Idee war ein riesiges Array, aber ich denke, dies wird dazu führen, dass der Speicher knapp wird. Vielleicht muss ich nur die Blöcke in der Nähe des Players laden.
Wie kann ich mit dem Laden der benötigten Blockinformationen aus einer Datei und dem Speichern nur der benötigten Informationen im Speicher umgehen?
c++
voxels
minecraft-modding
data
Danijar
quelle
quelle
Antworten:
Es gibt verschiedene Möglichkeiten, die Daten für ein Spiel mit Blöcken wie Minecraft zu speichern.
Ich glaube, Minecraft macht die Welt in den 16x16x256 Chunks. Die Blöcke um den Spieler werden in den Speicher geladen, wenn der Spieler das Spiel startet, und ein Hintergrund-Thread wird mehr geladen, wenn Sie herumlaufen. Hier ist ein Video, das es zeigt: http://www.youtube.com/watch?v=oR_ZdJH9eho .
Eine andere Möglichkeit besteht darin, die Welt in einen Octree zu zerlegen. Michael Goodfellow schrieb einen Blog über die Implementierung einer Cube-Welt mit dieser Datenstruktur: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html . Das Octree ist schön, weil es Ihnen eine eingebaute Komprimierung bietet, aber es wird wahrscheinlich etwas schwieriger sein, mit einem Array zu arbeiten.
Über die "nur benötigten im Gedächtnis behalten?" Dies ist etwas schwieriger, da Sie fragen müssen, was "benötigt" wird. Wenn Sie NPCs haben, die in einem anderen Teil der Welt mit KI leben, die mit der Umgebung interagiert, dann "brauchen" Sie viel mehr von der Welt, um im Gedächtnis zu bleiben. Voxel-Weltdaten können sehr schnell sehr groß werden. Versuchen Sie daher am besten, die geringstmögliche Menge im Speicher zu behalten. (IE, haben nur NPCs in der Nähe des Spielers).
Die Grafik-Engine "benötigt" jeden Block, der nicht vollständig von anderen nicht transparenten Blöcken umgeben ist. Die übliche Methode zum Rendern der Welt besteht darin, ein einzelnes Netz zu erstellen, das die Eckpunkte für jeden sichtbaren Block enthält. Das Zeichnen ist viel schneller, da Sie nur einen Aufruf der Zeichenmethoden für 65.536 Blöcke (in Blöcken in Minecraft-Größe) ausführen. Da die Grafik-Engine dieses Netz erstellen muss, muss sie im Allgemeinen alle Würfel in einem Block kennen. Beachten Sie, dass aus diesem Grund ein Großteil der Welt unsichtbar ist, wenn Sie in Minecraft durch den Boden sehen. Dies liegt daran, dass jeder Block, der auf allen sechs Seiten umgeben ist, übersprungen wird. Ich glaube, Minecraft reduziert auch die Anzahl der Eckpunkte, indem horizontale Seiten derselben Art von Textur in einem Feld kombiniert werden, wobei sich die Textur wiederholt.
Mein Rat wäre, mit den 16x16x256 Brocken zu gehen. Speichern Sie sie in einem Array, da Sie aufgrund des Aufbaus der Netz- und Spiellogik (Kollisionserkennung, Hinzufügen / Entfernen von Blöcken usw.) eine schnelle Iteration und Bearbeitung benötigen. Laden Sie dann so viele Brocken wie möglich in einem Kreis um den Player. Skalieren Sie die Anzahl der Blöcke für bessere oder schlechtere Computer nach oben oder unten.
Das Laden von Chunks wird die Leistung erheblich beeinträchtigen. Fügen Sie es daher in einen Thread ein, der es im Laufe der Zeit ausführt. Stellen Sie sicher, dass Sie 3 neue Chunks vollständig laden können, während ein Spieler von einem Ende eines Chunks zum anderen läuft.
quelle
Ich kann es vielleicht nicht am besten erklären, aber ich werde es versuchen.
Ich denke, der beste Weg, um zu verstehen, wie man es effizienter macht, ist, Voxel zu verstehen. Minecraft basiert auf Voxel, es werden nur Würfel anstelle von Kugeln usw. verwendet.
Grundsätzlich ist ein Voxel eine 3D-Form, deren Volumen sich dynamisch ändern kann, und wenn sich das Volumen ändert, ändert sich auch die Form. Ein Chunk ist eine X x X x X-Menge von Voxeln. So können Sie beispielsweise einen Block mit 16 x 16 x 16 Voxeln und dann eine X-Anzahl von Blöcken haben. Sie haben eine Distanz festgelegt, die Sie nicht in Ihre Berechnungen einbeziehen sollten, wenn der Spieler weiter als N von Brocken entfernt ist. Dies ist ein bisschen ähnlich wie bei Schnittabständen, müsste aber auch für jeden Block gelten. Auf diese Weise können Sie es so haben, dass Sie Ihren Spieler immer im mittleren Chunk eines beispielsweise 3x3-Sets von Chunks haben können.
Sie hätten also eine Klasse, um mit den einzelnen Voxeln umzugehen. Wir werden es Voxel_cl nennen. Und dann hätten Sie eine Klasse namens Chunk_cl, die sich mit dem Voxelblock befasst. Und dann hätten Sie eine Weltklasse, die alle Chunks generiert, die die Voxel erzeugen würden, genannt World_cl.
Anstelle eines riesigen Arrays von allem hätten Sie jetzt jederzeit ein Array von 9 Chunks, und in der Chunk-Klasse hätten Sie ein Array von 4096 Voxeln.
Bitte beachten Sie, dass dies eine ziemlich einfache Erklärung ist. Ich arbeite gerade an etwas mit Voxeln, also dachte ich mir, ich würde meine Eingabe einwerfen = -)
Weitere Informationen zu Voxeln finden Sie unter http://en.wikipedia.org/wiki/Marching_cubes
quelle
Sie können versuchen, nur sichtbare Oberflächen zu rendern. Der Computer verarbeitet Blockdaten im Hintergrund, während der Renderer nur mit dem arbeitet, was Sie sehen. 8x8 Chunks wären einfacher zu handhaben.
quelle