Minecraft-Klon für Windows, Mac OS X und Linux. Nur ein paar tausend Zeilen C mit modernem OpenGL (Shader). Online-Multiplayer-Unterstützung ist über einen Python-basierten Server enthalten.
http://www.michaelfogleman.com/craft/
Mac- und Windows-Binärdateien sind auf der Website verfügbar.
http://www.michaelfogleman.com/craft/
Siehe unten, um von der Quelle auszuführen.
Laden Sie CMake herunter und installieren Sie es, falls Sie es noch nicht haben. Sie können Homebrew verwenden, um die Installation zu vereinfachen:
brew install cmake
sudo apt-get install cmake libglew-dev xorg-dev libcurl4-openssl-dev
sudo apt-get build-dep glfw
Laden Sie CMake und MinGW herunter und installieren Sie sie. Fügen Sie C:MinGWbin
zu Ihrem PATH
hinzu.
Laden Sie cURL herunter und installieren Sie es, sodass sich CURL/lib und CURL/include in Ihrem Programmdateiverzeichnis befinden.
Verwenden Sie die folgenden Befehle anstelle der im nächsten Abschnitt beschriebenen.
cmake -G "MinGW Makefiles"
mingw32-make
Sobald Sie die Abhängigkeiten haben (siehe oben), führen Sie die folgenden Befehle in Ihrem Terminal aus.
git clone https://github.com/fogleman/Craft.git
cd Craft
cmake .
make
./craft
Nach vielen Jahren wurde craft.michaelfogleman.com entfernt. Informationen zum Selbsthosting finden Sie im Abschnitt „Server“.
Sie können mit Befehlszeilenargumenten eine Verbindung zu einem Server herstellen ...
./craft [HOST [PORT]]
Oder mit dem Befehl „/online“ im Spiel selbst.
/online [HOST [PORT]]
Sie können Ihren eigenen Server betreiben oder sich mit meinem verbinden. Der Server ist in Python geschrieben, erfordert jedoch eine kompilierte DLL, damit er die Geländegenerierung genau wie der Client durchführen kann.
gcc -std=c99 -O3 -fPIC -shared -o world -I src -I deps/noise deps/noise/noise.c src/world.c
python server.py [HOST [PORT]]
/goto [NAME]
Teleportieren Sie sich zu einem anderen Benutzer. Wenn NAME nicht angegeben ist, wird ein zufälliger Benutzer ausgewählt.
/list
Zeigt eine Liste der verbundenen Benutzer an.
/login NAME
Wechseln Sie zu einem anderen registrierten Benutzernamen. Der Anmeldeserver wird erneut kontaktiert. Beim Benutzernamen wird die Groß-/Kleinschreibung beachtet.
/logout
Deaktivieren Sie die Authentifizierung und werden Sie Gastbenutzer. Automatische Anmeldungen werden erst wieder durchgeführt, wenn der Befehl /login erneut ausgegeben wird.
/offline [FILE]
Wechseln Sie in den Offline-Modus. FILE gibt die zu verwendende Sicherungsdatei an und ist standardmäßig auf „craft“ eingestellt.
/online HOST [PORT]
Stellen Sie eine Verbindung zum angegebenen Server her.
/pq P Q
Teleportiere dich zum angegebenen Chunk.
/spawn
Teleportiere dich zurück zum Spawnpunkt.
Das Gelände wird mithilfe von Simplex-Rauschen generiert – einer deterministischen Rauschfunktion, die basierend auf der Position gesät wird. Die Welt wird also an einem bestimmten Ort immer auf die gleiche Weise erzeugt.
Die Welt ist in der XZ-Ebene (Y ist oben) in 32x32-Blockblöcke aufgeteilt. Dadurch kann die Welt „unendlich“ sein (Gleitkomma-Präzision ist derzeit bei großen X- oder Z-Werten ein Problem) und es wird auch einfacher, die Daten zu verwalten. Es müssen nur sichtbare Blöcke aus der Datenbank abgefragt werden.
Es werden nur freiliegende Gesichter gerendert. Dies ist eine wichtige Optimierung, da die überwiegende Mehrheit der Blöcke entweder vollständig verborgen ist oder nur eine oder zwei Flächen freilegt. Jeder Block zeichnet eine Überlappung von einer Blockbreite für jeden benachbarten Block auf, sodass er weiß, welche Blöcke entlang seines Umfangs freigelegt sind.
Es werden nur sichtbare Teile gerendert. Mithilfe eines naiven Frustum-Culling-Ansatzes wird getestet, ob sich ein Brocken im Sichtfeld der Kamera befindet. Ist dies nicht der Fall, wird es nicht gerendert. Dies führt auch zu einer recht ordentlichen Leistungsverbesserung.
Chunk-Puffer werden vollständig neu generiert, wenn ein Block in diesem Chunk geändert wird, anstatt zu versuchen, das VBO zu aktualisieren.
Der Text wird mithilfe eines Bitmap-Atlas gerendert. Jedes Zeichen wird auf zwei Dreiecke gerendert, die ein 2D-Rechteck bilden.
Es wird „modernes“ OpenGL verwendet – es werden keine veralteten Pipeline-Funktionen mit fester Funktion verwendet. Vertex-Pufferobjekte werden für Positions-, Normalen- und Texturkoordinaten verwendet. Zum Rendern werden Vertex- und Fragment-Shader verwendet. Matrixmanipulationsfunktionen für Translations-, Rotations-, Perspektiven-, orthografische usw. Matrizen befinden sich in „matrix.c“. Die 3D-Modelle bestehen aus sehr einfachen Grundkörpern – meist Würfel und Rechtecke. Diese Modelle werden im Code in Cube.c generiert.
Transparenz in Glasblöcken und Pflanzen (Pflanzen nehmen nicht die vollständige rechteckige Form ihrer Dreiecksprimitive ein) wird durch das Verwerfen magentafarbener Pixel im Fragment-Shader implementiert.
Benutzeränderungen an der Welt werden in einer SQLite-Datenbank gespeichert. Es wird nur das Delta gespeichert, daher wird die Standardwelt generiert und dann werden die Benutzeränderungen beim Laden zusätzlich angewendet.
Die Hauptdatenbanktabelle heißt „Block“ und hat die Spalten p, q, x, y, z, w. (p, q) identifiziert den Block, (x, y, z) identifiziert die Blockposition und (w) identifiziert den Blocktyp. 0 steht für einen leeren Block (Luft).
Im Spiel speichern die Chunks ihre Blöcke in einer Hash-Map. Eine (x, y, z)-Taste wird einem (w)-Wert zugeordnet.
Die Y-Position von Blöcken ist auf 0 <= y < 256 begrenzt. Die Obergrenze ist hauptsächlich eine künstliche Begrenzung, um zu verhindern, dass Benutzer unnötig hohe Strukturen bauen. Benutzern ist es nicht gestattet, Blöcke bei y = 0 zu zerstören, um nicht unter die Welt zu fallen.
Der Mehrspielermodus wird mit einfachen, alten Sockets implementiert. Es wird ein einfaches, zeilenbasiertes ASCII-Protokoll verwendet. Jede Zeile besteht aus einem Befehlscode und null oder mehr durch Kommas getrennten Argumenten. Der Client fordert Chunks vom Server mit einem einfachen Befehl an: C,p,q,key. „C“ bedeutet „Chunk“ und (p, q) identifiziert den Chunk. Der Schlüssel wird zum Zwischenspeichern verwendet – der Server sendet nur Blockaktualisierungen, die seit der letzten Anfrage des Clients nach diesem Block durchgeführt wurden. Blockaktualisierungen (in Echtzeit oder als Teil einer Chunk-Anfrage) werden im folgenden Format an den Client gesendet: B,p,q,x,y,z,w. Nachdem alle Blöcke für einen angeforderten Block gesendet wurden, sendet der Server einen aktualisierten Cache-Schlüssel im Format: K,p,q,key. Der Client speichert diesen Schlüssel und verwendet ihn, wenn er das nächste Mal nach diesem Block fragen muss. Spielerpositionen werden im Format gesendet: P,pid,x,y,z,rx,ry. Die PID ist die Spieler-ID und die Werte rx und ry geben die Drehung des Spielers in zwei verschiedenen Achsen an. Für eine flüssigere Animation interpoliert der Client die Spielerpositionen aus den letzten beiden Positionsaktualisierungen. Der Client sendet seine Position höchstens alle 0,1 Sekunden an den Server (weniger, wenn er sich nicht bewegt).
Das clientseitige Caching in der SQLite-Datenbank kann leistungsintensiv sein, wenn zum ersten Mal eine Verbindung zu einem Server hergestellt wird. Aus diesem Grund werden SQLite-Schreibvorgänge in einem Hintergrundthread ausgeführt. Aus Leistungsgründen erfolgen alle Schreibvorgänge in einer Transaktion. Die Transaktion wird alle 5 Sekunden festgeschrieben, im Gegensatz zu einem logischen Arbeitsaufwand. Als Warteschlange für die Daten, die in die Datenbank geschrieben werden sollen, wird ein Ring-/Zirkelpuffer verwendet.
Im Mehrspielermodus können sich die Spieler gegenseitig in der Hauptansicht oder in einer Bild-in-Bild-Ansicht beobachten. Die Implementierung des PnP war überraschend einfach: Ändern Sie einfach das Ansichtsfenster und rendern Sie die Szene erneut aus der Sicht des anderen Spielers.
Treffertests (auf welchen Block der Benutzer zeigt) werden implementiert, indem ein Strahl von der Position des Spielers nach außen gescannt wird und dabei seinem Sichtvektor folgt. Dies ist keine präzise Methode, daher kann die Schrittrate kleiner gemacht werden, um eine höhere Genauigkeit zu erzielen.
Beim Kollisionstest wird lediglich die Position des Spielers so angepasst, dass er einen bestimmten Abstand zu benachbarten Blöcken einhält, die Hindernisse darstellen. (Wolken und Pflanzen sind nicht als Hindernisse markiert, Sie passieren sie also direkt.)
Für den Himmel wird eine strukturierte Himmelskuppel verwendet. Die X-Koordinate der Textur stellt die Tageszeit dar. Die Y-Werte werden von der Unterseite der Himmelskugel bis zur Oberseite der Himmelskugel abgebildet. Der Spieler befindet sich immer im Zentrum der Kugel. Die Fragment-Shader für die Blöcke tasten auch die Himmelstextur ab, um basierend auf der Position des Blocks relativ zum Hintergrundhimmel die geeignete Nebelfarbe zum Mischen zu bestimmen.
Umgebungsokklusion wird wie auf dieser Seite beschrieben implementiert:
http://0fps.wordpress.com/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/