Ein Maratis3D Game-Plugin mit Linux

Ein Maratis3D Game-Plugin mit Linux

Yannick Pflanzer

26. Mai 2013

Inhaltsverzeichnis

1 Vorwort

Die Maratis3D Game Engine besitzt die Möglichkeit durch ein Game Plugin Standardkomponenten der Engine auszutauschen oder sogar eigene hinzuzufügen. Im Folgenden werde ich auf die benötigten Schritte zur Erstellung eines Game-Plugins in einer Linux Umgebung eingehen.

1.1 Markierungen und Code

Sourcecode wird wie folgt dargestellt:

int main(int argc, char* argv[])  
{  
    return 0;  
}

-

Schreibweise von Pfaden: Pfad=>Zur=>Datei

Diese Pfadangaben sind möglichst allgemein gehalten.

2 Voraussetzungen

Um ein Plugin unter Linux zu kompilieren benötigt man:

Außerdem benötigt man einen Texteditor. Dieser darf jeder Texteditor sein, den Sie verwenden möchten. Diese Tools sollten größtenteils in den Standardrepositories Ihrer Linux Distribution vorhanden sein wobei das offizielle Maratis SDK von der Maratis Downloadseite heruntergeladen werden muss. Die offizielle Maratis3D website ist unter http://www.maratis3d.org zu finden.

Um das Plugin in einem Maratis Projekt nutzen zu können muss zunächst ein Projekt mithilfe des Maratis Editors, welcher dem SDK beiliegt, erstellt werden.

3 Das Game-Plugin

3.1 Was ist ein Game-Plugin?

Ein Maratis Game-Plugin ist eine Windows *.dll, Linux *.so oder OS X *.dylib Datei, welche Code für Behaviourals (Verhaltensweisen) und den Ersatz verschiedenster Maratis Standardkomponenten enthalten kann. Behaviourals sind Programmteile, welche einem Objekt des Spiels zugeordnet werden und mit diesem Objekt ein bestimmtes Verhaltensmuster erzeugen. Ein Beispiel für die Verwendung einer Verhaltensweise ist die Logik eines Computergegners in einem Spiel. Aus dem Plugin können auch Teile für das Lua Interface zur Verwendung freigegeben werden. Dadurch ist es möglich rechenintensive Programmteile statt in ’langsamen’ Lua in ’schnellem’ C++ zu schreiben um damit Rechenzeit zu sparen und letztendlich die Systemanforderungen zu senken. Das Plugin muss in Maschinencode vorliegen weshalb der Sourcecode vor der Verwendung Kompiliert werden muss.

3.2 Standard Buildordner des Buildsystems

Bevor wir mit dem Plattform-spezifischen Teil des Buildsystems beginnen können müssen wir erst einmal eine einheitliche Ordnerstruktur schaffen um den Code später einfacher auf mehrere Plattformen portieren zu können. Dafür wird der Ordner mit dem Namen ’_GamePlugin’ im Maratis Projektordner erstellt. Im neuen Ordner wird noch ein weiterer Unterordner mit dem Namen ’Sources’ erstellt, sodass folgende Ordnerstruktur vorhanden ist:

Projekt=>_GamePlugin=>Sources

3.3 Erstellung des Game-Plugins mit Linux

Das Plugin wird mit g++ als Compiler gebaut und das ganze gegen die Maratis Engine gelinkt. Verwendet wird folgende Makefile welche die richtigen Parameter für g++ zusammenbaut:

Makefile:

 
SRCS = $(wildcard *.asm *.c *.cpp *.S)  
OBJS = $(addsuffix .o,$(basename $(SRCS)))  
 
CC = gcc  
CPPC = g++  
 
CFLAGS= -fPIC  
 
LIBPATH= -L../SDK/MCore/Libs -L../SDK/MEngine/Libs  
LIBS= -lc -lstdc++ -lMCore -lMEngine  
INCLUDES= -I../SDK/MCore/Includes/ -I../SDK/MEngine/Includes/  
 
ARG= $(LIBPATH) $(LIBS)  
 
all: $(OBJS)  
    @$(CC) -shared -Wl,-soname,Game.so $(OBJS) -o Game.so $(ARG)  
    @cp Game.so ../../  
 
%.o: %.c  
    @echo "( Compiling $^ )"  
    @$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $^  
 
%.o: %.cpp  
    @echo "( Compiling $^ )"  
    @$(CPPC) $(CFLAGS) $(INCLUDES) -c -o $@ $^  
 
clean:  
    rm -f $(OBJS)  
 
.PHONY: clean all  

-

Die Pfade in LIBPATH und INCLUDES müssen gegebenenfalls an Ihr System angepasst werden. Dabei ist ’SDK’ der Pfad zur Maratis SDK. Allgemeingültig lautet der Pfad:

PfadZumSDK=>MCore=>Libs
PfadZumSDK=>MEngine=>Libs

für LIBPATH und

PfadZumSDK=>MCore=>Includes
PfadZumSDK=>MEngine=>Includes

für INCLUDES.

Der Pfad zum SDK kann auch ein relativer Pfad sein.

Nachdem diese Pfade eingetragen wurden kann man auch schon anfangen zu kompilieren. Dazu wechselt man mit dem Terminal in das Verzeichnis mit der Makefile Datei und gibt

make

-

in die Konsole ein. Daraufhin sollte die Kompilation beginnen wobei beim jetzigen Status nur Fehler ausgegeben werden, da noch keine Quelldateien für das Projekt erstellt wurden.

4 Die Makefile

Im vorigen Kapitel wurde eine Makefile für die Kompilation des Plugins erstellt und getestet. Hier möchte ich nun die genaue Funktionsweise dieser Datei erläutern.

4.1 Auswahl der Dateien

Eine Makefile ist dazu da alle Dateien eines Softwareprojektes zu kompilieren, zu linken und gegebenenfalls andere Operationen mit ihnen auszuführen. Dazu muss erst einmal herausgefunden werden, welche Dateien überhaupt einbezogen werden müssen. Wie macht man das?

In vielen Makefile Tutorials findet man die Verwendung einer festgelegten Liste mit Dateinamen als Angabe der Quellen. In meiner Makefile wird dies jedoch anders gelöst indem alle wichtigen Dateien automatisch bei jedem Build erkannt werden und somit in die Kompilation eingebunden werden.

SRCS = $(wildcard *.asm *.c *.cpp *.S)  
OBJS = $(addsuffix .o,$(basename $(SRCS)))

-

In diesen zwei Zeilen Code wird dies erledigt. Eingebunden werden alle Dateien mit den Endungen *.asm, *.c,. *.cpp und *.S. Wir benötigen zur Zeit nur *.cpp Dateien, daher können die Targets für die anderen Dateitypen vernachlässigt werden. Um die Dateinamen dem Compiler zu übergeben brauchen wir den Namen der resultierenden Objektdatei mit der Endung *.o. Diese Namen werden aus den Namen der Sourcedateien erzeugt und in der Variable ’OBJS’ gespeichert.

4.2 Vorbereitung der Kompilation

Bevor das Plugin kompiliert werden kann muss der Compiler eingerichtet werden. Dies geschieht indem die nötigen Konfigurations-Flags in Variablen zusammengefasst werden.

CC = gcc  
CPPC = g++  
 
CFLAGS= -fPIC  
 
LIBPATH= -L../SDK/MCore/Libs -L../SDK/MEngine/Libs  
LIBS= -lc -lstdc++ -lMCore -lMEngine  
INCLUDES= -I../SDK/MCore/Includes/ -I../SDK/MEngine/Includes/  
 
$(ARG)= $(LIBPATH) $(LIBS)

-

Hier wird zunächst der verwendete Compiler festgelegt: Für C-Dateien gcc und g++ für C++ Dateien. Wichtig für das Ergebnis des Linkers ist das Flag ’-fPIC’ welches dem Compiler mitteilt, den Maschinencode Positionsunabhängig zu produzieren. Das hat alleine den Zweck, dem Linker die Erstellung einer Linux Bibliothek als *.so Datei zu ermöglichen. In den Variablen ’LIBPATH’ und ’LIBS’ werden die benötigten Bibliotheken der Maratis SDK eingestellt, damit das Plugin auf Maratis spezifische Funktionalitäten zurückgreifen kann. Außerdem müssen die C und C++ Standardbibliotheken eingebunden werden damit der Zugriff auf Dinge wie die C++ String Klasse möglich sind. Die Variable ’INCLUDES’ sorgt dafür, dass innerhalb des C/C++-Codes einfach per #include-Direktive auf die Header der Maratis SDK zugegriffen werden können. Um die Nutzung dieser Pfade zu vereinfachen werden beide Variablen in ’ARG’ gespeichert.

4.3 Die eigentliche Kompilation

Die eigentliche Kompilation wird durch Programmiersprachen spezifische Make-Targets übernommen.

all: $(OBJS)  
    @$(CC) -shared -Wl,-soname,Game.so $(OBJS) -o Game.so $(ARG)  
    @cp Game.so ../../  
 
%.o: %.c  
    @echo "( Compiling $^ )"  
    @$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $^  
 
%.o: %.cpp  
    @echo "( Compiling $^ )"  
    @$(CPPC) $(CFLAGS) $(INCLUDES) -c -o $@ $^  
 
clean:  
    rm -f $(OBJS)

-

  1. all: Dies wird jedes mal aufgerufen, wenn das Projekt kompiliert wird. Es ruft für jede Quelldatei den entsprechenden Compiler (meist g++) auf um daraus die Datei Game.so zu bauen und in das Projektverzeichnis des Maratis Projektes zu kopieren.
  2. %.o: %.cpp Hier werden alle *.cpp Dateien kompiliert.
  3. %.o: %.c Hier werden alle *.c Dateien kompiliert.
  4. clean: Mit dem clean Target werden alle erzeugten *.o Dateien gelöscht und so die Buildumgebung aufgeräumt.

Man beachte die Verwendung der vorher definierten Konfigurationsvariable ’ARG’ um die Bibliotheken und die Objektdateien mit gcc zu einer *.so zu linken.

5 Verwendung

Die Verwendung des Plugins erfolgt automatisch, wenn die Datei ’Game.so’ im selben Ordner zu finden ist wie das Maratis Projekt. Das Plugin wird auch automatisch eingebunden, wenn das Projekt mithilfe des Editors veröffentlicht wird.