Enginepfad

Aus DGL Wiki
Wechseln zu: Navigation, Suche

Der Enginepfad

Einführung

Willkommen auf dem Enginepfad des DelphiGL-Wikis. Dieser Pfad soll euch zeigen wie man eine Engine von Grund auf konzipieren und realisieren kann.

Wie funktioniert der Trampelpfad? Im nachfolgenden Abschnitt findet ihr einen Text, der euch etwas über Engines erzählen soll. Dieser Text ist durchsetzt mit Schlagwörtern, welche Links auf andere Artikel im Wiki sind. Wenn ihr diesen Links folgt, erfahrt ihr mehr zu den entsprechenden Themen.

Sinn des Trampelpfades ist es, euch die Artikel aufzuzeigen, welche ihr gelesen haben solltet und welche nützlich für den Einstieg in OpenGL sind. Am Ende dieses Trampelpfades findet ihr noch Links, die euch die Materie genauer erklären werden.

Der Trampelpfad

Am Beginn steht bei den meisten Anfängern zum Thema Engine die Frage "Was brauch' ich um eine Engine zu entwickeln?". Je nach dem welches Betriebsystem ihr als Plattform gewählt habt, können sich die Hilfsmittel unterscheiden.


Weiterhin ist die Wahl der Sprache zu treffen. Wenn ihr mit Object Pascal in seinen vielen Varianten (z.B. Delphi) arbeiten wollt, dann ist der DGLOpenGL.pas-Header genau das richtige für euch. Wenn es eine andere Sprache sein soll, müsst ihr euch dann nach einen aktuellen Header in Google umschauen. Es ist im vorhinein schon zu erwähnen, dass dieses Wiki Object Pascal in seiner Vielfalt verwendet.

Vorbereitung

Als erstes muss uns klar werden, welches Ausmaß die Engine erreichen soll. Davon abhängig ist unsere Planung zu gestalten:

1. Es ist ratsam mit der Plattformunterstützung anzufangen, da diese unsere unterste Schicht bilden wird.
Hier ist als erstes zu sagen, je mehr Plattformen unterstütz werden sollen, desto aufwendiger wird das Projekt.
Mit Plattformen sind hier z.B. PC mit 32Bit/64Bit, Konsolen (PS1-3, XBox-360, Wii, GP2X, ...) und mobile Geräte (Palm, PSP,...) gemeint.
Für jede Plattform gibt es eine oder mehrere Betriebssysteme zur Ansteuerung der Hardware.
Hier eine kleine Liste mit verschiedenen Betriebssystemen:
  • Windows
  • Linux
  • MacOS X


2. Abhängig davon wählen wir nun unseren Compiler.
  • Delphi (Windows 32Bit)
  • FreePascal (Unterstützung für alle erwähnten Plattformen und OS)
  • gcc (Unterstützungen für alle erwähnten Plattformen und OS)
  • Kylix (Linux 32Bit) (Veraltet, nicht mehr in Entwicklung)
  • VisualC++ (Windows 32/64Bit WinCE)


3. Nun sollten wir entscheiden, welche Bibliothek wir für das Ansprechen der Grafikkarte verwenden:
Es gibt einige wie z.B. DirectX, GDI, AGG und Mesa aber wir wollen uns mit OpenGL auseinander setzen, denn dieses ist ein OpenGL Wiki.
Info DGL.png Dieser Verweis führt Sie auf den Verwendungspfad in diesem Wiki und soll zeigen wie man OpenGL unter den einzelnen OS nutzten kann


4. Nun kommen wir zu allgemeinen Bibliotheken für das Ansteuern unserer Hardware.
Im Voraus ist zu sagen, dass ALSA und OSS Treiber unter Linux sind, die das Abspielen von Sound ermöglichen. Nur nur ein Bruchteil der Bibliotheken ist für 3D Sound ausgelegt und man müsste bei Bedarf noch einen eigene Dopplereffekt hinzufügen.
Sound:
Netzwerk:
  • DirectX Net (Windows)
  • SDL_Net
  • Raknet


5. Jetzt sollte man entscheiden, ob und welche Bibliotheken man zur Erleichterung der nicht hardwarebezogenen Aufgaben wählt. Um den Rahmen nicht zu sprengen nur ein paar Beispiele.
Physik:
Fenster:
Kompression:
Künstliche Intelligenz:


6. Nun beachten wir unser eventuell eingeplantes Budget (normalerweise 0€ ^_^) und gehen die Liste oben nochmal durch.


7. Ein Programm teilt sich in der Regel in 3 Teilbereiche (im Bereich Software Engineering auch Pakete genannt), diese sind die GUI, die Programmlogik und die Datenbank.
GUI:
  • Die GUI sorgt dafür, dass alle Informationen dem User grafisch dargestellt werden. Dabei geht dieses natürlich auch in die Gegenrichtung. Also der User gibt Informationen an den Computer.
Logik:
  • Die Logik ist der größte Teil vom Programm, denn hier ist der ganze Code angesiedelt, der das Programm zum laufen bringt.
Datenbank:
  • Das Datenbank Paket, ist der Part wo alle Daten, die das Programm benötigt, zwischengespeichert werden. Das wären z.B. Variablen, Texturdaten, Spielerinformationen und so weiter.


Wer sich in der Material nur ausprobieren will, kann anfangen, so viel wie möglich selber zu programmieren. Wenn es aber darum geht, eine Engine zu schreiben, welche man auch benutzten will, dann sollte man versuchen, so viel Code wie möglich wieder zu verwerten. Viele Programmierer haben schon Funktionen, Strukturen und Lösungen geschrieben und diese gilt es so gut wie möglich wieder zu verwerten. Dies hat viele Vorteile, denn man spart Zeit, man kann sich sicher sein, dass der Code standardmässig läuft und man hat sich viel Zeit mit der Konzeptphase gespart. Man muss in der konstruktiven Entwicklung nicht mehr das Rad neu erfinden. Der Trend in der professionellen Programmierung geht seit vielen Jahren in diese Richtung. SDL, OpenAL, DirectX, OpenGL, zLib und viele andere Bibliotheken haben sich so ihren Stellenwert erkämpft.

Helfende Tools

Wenn man ein Projekt beginnt, dann sollte man auch entsprechend ausgerüstet sein, denn eine gute Toolchain erspart viel Zeit.

Versionierung

Unabhängig von der Größe eines Projektes sollte der Quellcode und die damit verbundenen Ressourcen Versioniert werden, damit keine Daten verloren gehen. Hier mal eine Liste mit Versionierungstools.

  • SVN(frei,OpenSource,cross platform, der Nachfolger von CVS)
  • git(frei,OpenSource,cross platform, der Linuxkernel wird darüber verwaltet)
  • CVS(frei,OpenSource,cross platform, weit verbreitet)
  • Perforce(kommerziel ab 2 Nutzern,closed Source,cross platform, im Komerziellen Bereich verbreitet z.B. UnrealEngine3)

Unit Test

Hierfür gibt es je nach Sprache und geschmack mehere Möglichkeiten.

Ein Unittest dient dazu, einen einzelne Funktion aus dem großen ganzen zu testen und alle Unittests zusammen ergeben dann die benötigte Funktionalität der Software. Schlagen einige Unittests fehl, tut die Software nicht mehr das, was sie eigentlich Leisten sollte. Wenn wir z.B. eine Aufgabe haben "berechne Hashwert von einer Datei", dann würden wir unsere Funktion, die einen Hashwert berechnet, in mehrere Unit Tests zerlegen und einen Unit Test anlegen, der die Hashfunktion auf eine Dummy File IO Klasse testet. Die Dummyklasse ist in der Regel ein Interface, welcher Konstante Daten enthält und somit eine 100% funktionierende Netzwerkverbindung, Datenbank, Dateisystem oder ähnliches Simuliert. Das hat den Vorteil, dass unsere Unittest auf jedem System laufen, auch wenn garkeine Netzwerkkarte da ist. Denn wir wollen ja die Funktionalität testen und nicht die Lauffähigkeit auf irgendwelchen Systemen. Mehr zum Thema ist hier zu finden.

Automatisierte Builds können sehr Hilfreich sein.

Ein Automatisierter Build wird verwendet, um z.B. Nightbuilds, Dailybuilds zu erstellen, Unittest, Systemtest und so weiter zu machen. Die komplexität von Buildsystemen ist hierbei sehr unterschiedlich. Hier ein paar Tools.

  • make
  • scons(python basierte toolchain, cross platform)
  • CMake(Projektdatei Generator für viele Buildsysteme)
  • Ant(java basierte toolchain, cross platform)

So kann man z.B. sein Projekt in einer makefile umsetzen, indem man sogenannte Targets für Kompilieren, Aufräumen, Unittests einbaut. Wenn man dann als Programmierer den Sourcecode lädt, kann man einfach make machen und man bekommt ein fertiges Build zurück. Damit hat man den ersten Stein für den Weg, zur nutzung der Software, gelegt. Der neue Programmierer will sich nicht erst mit den ganzen Konfigurationen, abhängigkeiten und Flags beschäftigen und wenn man als Entwickler der Software nach 1Jahr wieder den Code generieren will und die Befehle nicht mehr weiß, hat man sogar selber die Probleme. Daher lohnt es sich schon gleich zum anfang sich ein Generierungssystem auszusuchen und diese mit neuen Datein immer zu aktualisieren.

Komplexe Buildsystem

Wer vor hat an ein größeren Projekt zu arbeiten, der sollte sich ein Buildsystem zulegen, welches über make und anderen hinaus geht. Eines der weit verbreitesten Systeme ist CruiseControl. CruiseControl ist ein Buildsystem, im welchen man Projekte anlegen kann, diesen bestimmte Aufgaben zuweist und es selbständig für sie Arbeit verrichtet. So kann man das erstellen von Binaries, UnitTest und Systemtest durchführen, Installer erstellen, E-Mails versenden und noch vieles mehr. Mehr zu CruiseControl findet man hier.

Systemtests

Systemtests sind Tests, die auf eine möglichen Zielumgebung ausgeführt werden, um zu sehen ob noch Funktionen in der Software fehlen. Wenn z.B. die Netzwerkverbindung mittem beim Senden zusammenbricht und daraus ein Fehler entsteht. Der Unittest testet ja nur die Funktion selber erfolgreich aber nicht System oder Fremdcode Fehler. Buildtools wie Ant in Verbindung mit CruiseControl können Systemtests sehr angenehm zu testen machen und vorallem automatisiert.

Design Brainstorming

Wenn es mal wieder Zeit ist und ein neues Feature implementiert werden soll, dann sollte man sich erstmal einem Brainstorming unterziehen und dazu sind Tools hilfreich, die einfach nur die Gedanken widerspiegeln und nicht auf UML oder ähnliche Konzepte basieren. Denn man will in dieser Phase noch nichts konkretes sondern nur Lösungsansätze. Hierfür gibt es komerzielle und freie Tools, die entsprechend unterschiedlich viel können und arbeiten.

  • FreeMind(freies OpenSource Tool, cross platform)
  • Labyrinth(freies OpenSource Tool, Linux only)

Planung

Wir gehen mal von ein "AllInOne Wonder" aus und nutzen FreePascal aufgrund der Plattformunabhängigkeit, SDL und sämtliche Zusatzpakete zur plattformunabhängigen Fensterinitialisierung sowie zum Laden von etlichen Bildformaten. Für die Soundausgabe werden wir aufgrund von Kostengründen auf OpenAL setzen. Für die Physik ist eine vorhandene Bibliothek wie zum Beispiel ODE zu favorisieren, da diese schon ausgereifter als eine selbst entwickelte ist. Doch kann im Gegenzug eine eigene Physik-Bibliothek eventuell schneller und viel schlanker sein, wenn man nur eine handvoll Dinge benötigt.


Geht's nun Los?


Na ja, nun kommt der wahrscheinlich unangenehmste Satz für alle:


Die Entwicklung einer Engine bedarf einer ausführlichen Planung, was kurz und knapp ein Softwarecycle bedeutet. Nun sollte man die einzelnen Schritte eines Softwarecycles abarbeiten und ganz am Ende, wenn viel Zeit rum ist, kann man dann endlich anfangen den Compiler flott zu machen. Kleiner Tipp: Macht euch die Mühe, da diese sich umso mehr auszahlt, je grösser das Projekt ist(für ein Packman Clon ist es aber eher Zeitverschwendung). Das Allerwichtigste bei großen Projekten ist, dass Aufgabenpakete/Module geschnürt werden. Diese sollten nach dem Blackbox-Prinzip erstellt werden. Dadurch können die Module unabhängig voneinander von verschiedenen Personen erstellt werden. Um so etwas realisieren zu können, ist natürlich klar, dass in die Planung der Schnittstellen zwischen den Modulen sehr viel Zeit eingesetzt werden sollte. Änderungen in den Modulen sind kein Problem, Änderungen an der Schnittstelle können Einfluss auf das gesamte Projekt haben. Eine Engine kann entweder auf Low-Level oder High-Level API aufsetzen, idealerweiser sollte man eine Zwischenlösung nutzen, hierzu finden Sie unter High/Low-Level API weitere Informationen.

In der Industrie verwendet man in größeren Engines Wrapper. Dieser ist dazu da, dass OpenGL/SDL und DirectX über eine eigene API angesteuert werden kann und somit ist es möglich die Engine mit den verschiedensten Plattformen (PC, Konsole, etc.) zurecht kommt. Laut einer neueren Umfrage schreiben 75% alle amerikanischen Publisher ihren Entwicklerteams vor, dass sie eine Engine mit genau dieser Eigenschaft nutzen. Des weiteren ist es auch immer häufiger, dass Publisher auf der ganzen Welt ihren Entwicklerteams vorschreiben, dass sie eine fertige Engine (Middleware) zu verwenden haben. Dies hat den Grund, dass der Publisher somit das Risiko eines Spiels vermindert und Geld spart - schließlich kostet das Entwickeln einer Engine eine große Summe an Geld und die Künstler sitzen währenddessen ohne Arbeit herum. Diese kalkulierten Kosten sind in der Summe höher als der Preis einer aktuellen Engine, wie zum Beispiel die "Vision" oder "Source" Engine.

Wenn Sie es noch nicht getan haben, dann schauen Sie sich am besten noch ein Buch oder Artikel über Pattern/Muster an. So sind Adapter, Singleton, Observer Muster sehr sinnvoll zu kennen. So kann man z.B. für Materials, Texturen, Shader, Models, Animationen und alle anderen auf Daten basierte Komponenten mit dem Adapter Muster sehr flexibel sein. Für ein SceneGraph kann man das Observer Muster prima anwenden und Singleton kann man für alle Manager verwenden.

Info DGL.png Siehe die Tutorial Reihe Softwareentwicklung

Die ersten Schritte in eine nicht reelle Welt

Nachdem man weiß, was das Projekt einmal enthalten soll, besteht der erste Schritt darin, Manager zu erstellen, die die Arbeit erleichtern. Bei 3D-Spielen ist z.B. ein Leveleditor kein Feature, was am Ende entwickelt wird, sondern der Editor ist fertig, noch bevor das Spiel getestet wird. Deshalb gibt es in Firmen Programmierer, die nichts anderes machen als Tools/Manager für die Erstellung der Inhalte zu fertigen. Dazu gehören:

  1. Leveleditoren um die "Welt" zu erstellen.
  2. Texturmanager um den Programmierern den Zugriff auf die Texturen so einfach wie möglich zu machen.
  3. Soundmanager (siehe vorheriges)
  4. Lademanager für eigene Dateiformate.


Nun ist es so weit, wir wissen was wir wollen und haben alles durchdacht. Nun gilt es die einzelnen Module in die Tat um zu setzen. Einige Module die es 3D Anwendungen/Spielen geben könnte:


Grundlagen:

  1. Template
  2. Kamera
  3. Schrift
  4. Input (Maus/Tastatur)
  5. Adapter Muster


Fortgeschrittene Grundlagen:

  1. Sound
  2. Physik
  3. Texturen
  4. Levelformat
  5. Modelformat
  6. Console (Laufzeit-Schnittstelle zur Engine)
  7. GUI (Game User Interface)
  8. Netzwerk


Fortgeschritten:

  1. Shader
  2. Materials
  3. Packformate
  4. VFS (Virtual File System)
  5. Soundformat-Erweiterungen
  6. KI
  7. Script
  8. Scene Graph


Sieht doch eigentlich nach nicht so viel aus oder?


Doch der Schein trügt. In großen Firmen sitzen meist mehrere Programmierer, die in diesen Gebiet erfahren sind, an nur ein, maximal 2 Modulen. Wie ist es dann möglich, dass es trotzdem so viele Spiele/Engines gibt, die nicht von Firmen sind ?

  1. die Planung wird bei weitem nicht so groß ausfallen wie in Grossfirmen
  2. die Koordination von vielen Person ist sehr schwer und es kann zu großen Zeitlücken kommen
  3. meistens wird die Planung sowieso nicht in die Tat umzusetzen sein, es gibt immer ein Problem
  4. ein kleines Team kann sich im besten Fall gegenseitig hochpushen und zu mehr anspornen
  5. Großfirmen haben selten die Möglichkeit, mal einen Codefetzen in Foren zu setzen und verbessern zu lassen
  6. das Nutzen von Bibliotheken ist sehr zeitsparend

Die Engine ist fertig oder doch nicht?

Es gibt ein Unterschied zwischen der Entwicklung von einer Engine und der Entwicklung einer Engine für ein Spiel. Die Engine für ein Spiel ist festgelegt und hat ein Endpunkt, was sie leisten soll. Eine Engine als selbststehendes Projekt wird hingegen nie fertig, man kann sie immer wieder optimieren und erweitern. Doch kommt der Punkt, wo die Qualität den Ansprüchen völlig ausreichend ist. Man sollte nun noch überlegen, ob man eventuell ein Tool zur leichteren Handhabung der Engine entwickelt. So kann ein GUI-Editor oder Material-Editor die Arbeit um vieles erleichtern, wenn es dann heißt die Engine auch zu nutzen. Diese Tools nennt man dann die Toolchain einer Engine und dort gehören dann neben den Editoren auch Compiler, Libs und Ressourcen hinzu.

Nun bleibt es nur noch zu sagen: viel Glück und Erfolg mit der Entwicklung einer eigenen Engine. Mögen die bereitgestellten Links zur Erleuchtung führen.

Links

Karmarama Engine

Projekt omorphia

Andorra 2D