Aaron Fischer Ingenieur, Vater, Heimwerker, Problemlöser

23 Mai, 2016

Mapping

TL;DR:

Im letzten Teil haben wir uns die Quake 1 Engine genauer angesehen. In diesem Teil wollen wir sie modifizieren. Wir schauen uns an, wie die Quake Engine Änderungen erlaubt und wie Maps aufgebaut und compiliert werden.

Assets

Alle für das Spiel notwendigen Dateien werden in sog. PAK-Dateien gespeichert. Diese enthalten ähnlich wie ein Zip-Archiv ein Verzeichnisbaum, in dem Dateien abgelegt sind. Die *.pak-Dateien des Originalspiels sind im id1-Verzeichnis des Spiels zu finden. Liegen hier mehrere *.pak-Dateien, werden sie in alphabetischer Reihenfolge geladen. Für Mods sind PAK-Dateien ideal, da sie einfach zu handhaben sind und alles enthalten was benötigt wird.

Die Quake-Engine lädt nun eine PAK-Datei nach der anderen, und überlagert gleichnamige Dateien. Sind also zwei Dateien pak0.pak und pak1.pak vorhanden, in denen jeweils eine Map intro.bsp liegt, wird zuerst die Map aus pak0.pak geladen und dann mit der aus pak1.pak ersetzt. Zuletzt wird noch geprüft ob im id1-Verzeichnis ebenfalls eine intro.bsp liegt, welche dann ebenfalls die davor geladene Map überlagert. Man spricht hier auch von einem Overlay-Dateisystem.

So lässt sich jeder Teil (bis auf die Kernfunktionen Netzwerk, Rendering, Usereingaben etc.) überschreiben und modifizieren. Wird das ganze Spiel auf diese Weise umgebaut, nennt man es auch Total Conversion.

Texturen (WAD)

Texturen können in WAD-Dateien gruppiert werden, was sehr gerne bei Textur-Packs gemacht wird. WAD-Dateien sind -- ähnlich wie PAK-Dateien -- Container für eine Ansammlung von Dateien. In dem Fall ohne Verzeichnisstruktur. Die Vorgaben für Texturen sind hier relativ restriktiv. Dies macht es aber der Engine einfacher mit den Dateien zu arbeiten.

Texturen müssen im in Länge und Breite ein Vielfaches von 16px haben und in der 8 Bit Farbpalette gespeichert werden. Waser/Lava-Texturen müssen 64x64px große sein, Himmel-Texturen sind 256x128px. Größer als 320x192 dürfen sie aber nicht sein. Die Dateibenennung ist ebenfalls entscheidend. Flüssigkeiten fangen mit einem * an. Das Präfix slime und lava macht die Flüssigkeit automatisch zu Schleim oder Lava. Alles andere ist Wasser (kein Schaden).

Animationen fangen mit einem + an, gefolgt von der Framenummer. Eine Animationstextur mit zwei Frames besteht also aus zwei Dateien +0button und +1button. Himmel-Texturen fangen mit sky an.

Machen wir uns eine neue Textur und stecken diese in eine WAD-Datei, die wir dann vom Map-Editor und von der Quake Engine laden können. Mit Gimp lässt sich das einfach erledigen. Wichtig dabei ist, dass die Textur kachelbar ist, also dass der rechte Rand zum linken Rand passt und nahtlos übergeht.

textur

Dabei teilt man die Textur in 4 Bereiche und dreht diese so, dass die inneren Seiten nach außen zeigen. Das schwierigste dabei ist es, die äußeren Seiten im Inneren zusammenzuführen. Abschließend noch die Farben auf 256 reduzieren. Für den Dateinamen verwende ich gerne ein Prefix, so dass sie nicht mit anderen Texturen kollidiert.

Sind wir mit der Textur zufrieden, können wir sie in eine WAD-Datei stecken. Ich verwende dafür das Tool qpakman.

qpakman -g quake1 fu_stonefloor.png -o fu.wad

Zum Test, ob alles geklappt hat, können wir uns den Inhalt der WAD-Datei ansehen.

$ qpakman -l fu.wad 

**** QPAKMAN v0.67  (C) 2008 Andrew Apted ****

Opened WAD2 file: fu.wad
--------------------------------------------------
   1: +0000000c 0000bf68 M : fu_stonefloor
--------------------------------------------------
Closed WAD2 file

Mapping

Bevor wir mit der Map anfangen können, müssen wir noch ein paar Dinge einrichten. Ich arbeite mit NetRadiant (ein Ableger von GtkRadiant), da diese Version aktueller ist und mehr Features bietet. GtkRadiant geht natürlich auch. Nach der Installation benötigen wir zwei Dinge:

Beim Start von NetRadiant wird zuerst das Spiel abgefragt. Hier bitte Quake wählen, auch wenn wir Darkplaces (als Engine) verwenden. So findet NetRadiant dann später die Texturen.

NetRadiant

Danach noch schnell in die Settings (Edit->Settings) und den Pfad zur Quake 1 Installation angeben (den id1-Ordner auswählen). In diesem Ordner sollten dann auch die WAD-Dateien liegen. Danach sollte der Editor folgendermaßen aussehen:

NetRadiant

Nun können wir loslegen. Aber eines vorweg: Dies hier ist nicht als vollwertiges Handbuch zu NetRadiant zu verstehen. Ich zeige nur die minimalen Funktionen auf, die nötig sind, um eine ganz einfache Map zu bauen. Wer daran Gefallen findet, kann gerne hier weitermachen. Auch ganz hilfreich sind die Shortcuts.

Eine Map besteht aus Brushes (mit Texturen) und Entities. Brushes sind die Bauklötze, aus der die Map besteht. Diese können von allen Seiten mit jeweils einer Textur überzogen werden. Entities sind Elemente wie Waypoints, Waffen oder Spawn-Points, die in der Map platziert werden können. Wir werden für unsere erste Map 6 Brushes, zwei light Entities und ein info_player_start Entity brauchen.

Fangen wir mit dem info_player_start Entity an. Es hilft uns, die Größenverhältnisse etwas besser abzuschätzen. Rechtsklick auf die Arbeitsfläche und dann unter info -> info_player_start auswählen. Ein roter Kasten mit einem Pfeil taucht auf. Der Spieler ist in etwas so groß und wird an genau dieser Position starten, wenn die Map geladen wird. Der Pfeil zeigt die Blickrichtung an. Mit der Maus kann das Entity verschoben werden. Mit ESC wird die Auswahl abgewählt.

Als nächstes bauen wir den Raum. Dazu genügt es, mit der Maus ein Rechteck aufzuziehen. Mit CTRL+TAB kann die Ansicht gewechselt werden. So positionieren/skalieren wir den Block so lange, bis er als Bodenfläche passt. Mit ESC abwählen und wieder mit der Maus ein Rechteck aufziehen. So verfahren wir mit allen 4 Seitenwände, dem Boden und der Decke. Wichtig dabei ist allerdings, dass die so gebaute Box komplett dicht ist. Mit der Snap to Grid Funktion klappt das recht gut.

netradiant einrichten

Ist das geschafft, können wir noch die beiden Lichter in unserem Raum platzieren, so dass wir die Map später auch bewundern können. Dazu wieder mit einem Rechtsklick auf die Arbeitsfläche und light auswählen. Als Wert (Helligkeit) geben wir hier 160 an, das sollte genügen.

netradiant einrichten

Was jetzt noch fehlt, sind Texturen. Mit gehaltener SHIFT-Taste können wir mit der Maus in der 3D-Ansicht die Wand selektieren. Ist sie rot markiert, kann in dem darunterliegenden Texturbrowser eine Textur ausgewählt werden. Die Taste S öffnet den Surface Inspector, in dem die Textur dann noch bearbeitet werden kann (Position, Skalierung, Rotation, ...).

netradiant einrichten

Soweit sogut. Eine Kleinigkeit müssen wir noch einstellen, bevor wir die Map compilieren und testen können. Wir haben Texturen aus WAD-Dateien verwendet, die wir noch angeben müssen. Dazu L für Entity list drücken und dort worldspawn auswählen. Danach N für Entities drücken. Hier dann bei Wad File die beiden Dateien -- getrennt durch Semikolon -- angeben und mit ENTER bestätigen.

netradiant einrichten

Speichern nicht vergessen (ich habe die Map unter /usr/share/games/quake/id1/maps/aroom.map gespeichert).

Compilierung

Um die Map nun spielen zu können, müssen wir sie zuvor noch in das BSP-Format bringen. Dazu verwende ich hmap2 vom darkplaces Projekt. Hiermit müssen wir die Map in drei Schritten Compilieren.

Im ersten Schritt ist das BSP Rendering dran. Dabei werden alle nicht sichtbaren Seiten (faces) entfernt und die verbleibenden in einem BSP Baum gespeichert. Spätestens hier können wir sicherstellen, dass unsere Map von allen Seiten her dicht ist. Ist dies nicht der Fall, wirft der Compiler Fehlermeldungen.

cd /usr/share/games/quake/id1/maps/
hmap2 aroom.map

Im nächsten Schritt teilen wir die Map in Portale ein. Dies ist eine Optimierung für die Engine, welche wir auch überspringen können. Bei kleinen Maps macht dies bei einem aktuellen PC keinen spürbaren Unterschied. Doch bei größeren Maps macht dieser Schritt immer Sinn.

hmap2 -vis aroom.map

Und im letzten Schritt berechnen wir das Licht. Hat die Map ein Leak, kann dieser Schritt nicht ausgeführt werden und die Map wird überall gleich beleuchtet.

hmap2 -light aroom.map

Danach haben wir nun eine aroom.bsp, die wir mit der Quake Engine starten können.

Testen

Wir starten die Quake Engine mit darkplaces-sdl, öffnen mit ~ die Console und geben map aroom ein. Die Map sollte nun laden und uns an der von uns festgelegten Position starten lassen.

netradiant einrichten

Unsere erste Map ist fertig.

Map ausbauen

Das waren natürlich nur die minimal notwendigen Schritte, um eine Quake 1 Map zu erstellen und zu starten. Wir können nun die Map noch etwas ausbauen und mit Aktionen ausstatten. Versuchen wir folgendes: Sobald alle Gegner getötet wurden, öffnet sich eine Türe.

Zuerst erstellen wir die Türe. Dazu ziehen wir einen Brush auf, der einer Türe entspricht. Im noch ausgewählten Zustand dann mit dem Kontextmenü in eine func_door wandeln. (Rechtsklick func -> func_door). Die Einstellungen zur Türe können wir wie gewohnt mit N öffnen. Hier einen Haken bei toggle setzen und Open Direction auf up stellen (angle = -1). Als nächstes platzieren wir unsere drei Monster im Raum. Ich habe Knights genommen, um es ein bisschen anspruchsvoller zu machen :)

netradiant einrichten

Als letzten Schritt müssen wir noch unsere Logik einbauen. Dazu wieder einen kleinen Brush aufziehen und mit dem Kontextmenü zu einem trigger_counter wandeln. In den Einstellungen (N drücken) setzen wir Count auf 3. Jetzt wird es spannend: Wir selektieren alles ab (ESC), danach selektieren wir den ersten monster_knight und dann zusätzlich den trigger_counter. Nach einen Druck auf CTRL+k verbinden wir beide und eine rote Linie ist zu sehen. Dies machen wir mit den zwei verbleibenden monster_knights auch. Und anschließend verknüpfen wir so den trigger_counter mit der func_door. Eine lila Linie sollte erscheinen. Werden jetzt alle drei Monster getötet -- also der trigger_counter drei mal aktiviert -- wird dieser wiederum die Türe aktivieren.

Ich habe noch eine Waffe und etwas Munition, sowie ein Medpack hinzugefügt, um dem Spieler eine reelle Chance zu lassen :)

netradiant einrichten

Durch geschickte Kombination von Entities lassen sich so ganze Missionen erstellen. Wer mehr will, muss QuakeC schreiben. Und genau das werden wir im nächsten Teil machen.