Wie man mit einer Blockwelt wie Minecraft umgeht

9

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?

Danijar
quelle
2
Minecraft lädt die Welt in ziemlich großen Würfeln namens Chunks, nicht alle auf einmal. Ich bin mir der genauen Details nicht sicher. Die Minecraft-Quelle ist ziemlich einfach zu finden, wenn Sie einen Blick darauf werfen möchten, wie das gelaufen ist.
Ratbum
Tom van Green
Ich wusste bereits über Brocken in Minecraft Bescheid, aber trotzdem danke.
Danijar
Dies ist eine komplexe Frage, die für den Umfang dieses Blogs nicht geeignet ist.

Antworten:

9

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.

Thomas Marnell
quelle
Danke! Es gibt nichts über KI, weil ich einen Client für ein MMO schreibe. Die Berechnung der NPCs erfolgt durch den Server. Ein Zusatz: Nicht "jeder Block, der nicht vollständig von anderen nicht transparenten Blöcken umgeben ist" wird von der Grafik-Engine benötigt. Wenn es Höhlen gibt, kann der Spieler nicht sehen, dass sie unwichtig sind. ;-)
Danijar
2
Über Höhlen, die der Spieler nicht sehen kann ... Ich denke, es verbraucht weniger Leistung, um nur die Höhlen zu zeichnen, als um festzustellen, ob die Höhle vollständig blockiert war. Und wenn Sie keine Höhlen zeichnen, müssen Sie beim Entfernen eines Blocks möglicherweise das Netz für mehrere Blöcke anstatt nur für einen neu generieren. Es wäre cool, einen Weg zu finden, um Höhlen auszuschließen. Ich kann mir einfach keinen Weg vorstellen, dies effizient zu tun: D.
Thomas Marnell
3

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

Mungoid
quelle
3
Bei Marching Cubes geht es darum, Voxel zu visualisieren. Und Minecraft benutzt es nicht einmal; Es zeichnet nur Würfel, und genau darum geht es bei Marching Cubes nicht .
Nicol Bolas
Danke für Ihre Erklärung! Ich habe noch nie von Voxels gehört und es scheint sehr wichtig für mein Projekt zu sein. Aber ich habe jetzt noch eine Frage.
Danijar
Ich verstehe das Erstellen eines Arrays von Near Chunks, wobei jedes Element ein Array der Voxel dieses Chunks enthält. Aber dann muss ich das Chunk-Array ändern, wenn sich der Spieler in der Welt bewegt. Muss ich die benötigten Chunks aus der Sicherungsdatei lesen? Oder gibt es eine gute Möglichkeit, sie in Erinnerung zu behalten?
Danijar
2
@danijar Nur ein paar Kleinigkeiten, Pixel ist die Abkürzung für "Bildelement", Voxel wird auf die gleiche Weise aus "Volumenelement" gebildet. Nicht, dass es für irgendetwas wichtig wäre, aber da Sie den Begriff Voxel noch nicht gehört hatten, dachte ich, dass er für Sie von Interesse sein könnte.
Daniel Carlsson
1

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.

Gandalf
quelle