Spieleprogrammierung

Original Tetris unter Ubuntu mit Dosbox

Seit jeher begeistern Spiele jeder Art den Menschen. Egal ob es sich um Brettspiele, Kartenspiele oder sonst welche Spiele handelt, es gibt wahrscheinlich niemanden der nicht schon einmal irgendein Spiel gespielt hat. Kurz nach der Entwicklung der ersten Computer sind auch schon die ersten Spiele aufgetaucht. Eines der ersten Spiele, nämlich das aus Russland stammende Tetris, kennt selbst heute noch fast jeder. Wer übrigens die Originalversion einmal spielen möchte findet sie auf der Homepage von Vadim Gerasimov, einem der drei Entwickler der ersten Version. Da damals die unterschiedlichen Geschwindigkeiten der Prozessoren noch nicht berücksichtigt worden sind, kann es passieren, dass das Spiel etwas schnell ablaufen wird. Das Bild links ist ein Screenshot aus dem originalen Tetris mit Dosbox unter Ubuntu.

Da die Computer ständig weiterentwickelt und verbessert werden, hat man bei der Entwicklung von Spielen immer mehr Möglichkeiten, wodurch man mehr Leute ansprechen kann und Computerspiele immer weiter verbreitet und beliebter werden. Es hat sich sogar auch schon eine große Industriesparte entwickelt, die sich nur mit dem Erstellen von Computerspielen beschäftigt. Meines Wissens sind dabei die Umsätze schon höher als die der Filmproduktionen in Hollywood. Aber auch für uns als Hobbyentwickler ist es durchaus möglich eigene Spiele zu entwickeln, denn auch wenn es auf der ersten oder vielleicht auch auf den zweiten Blick überhaupt nicht danach ausschaut, so funktionieren alle Spiele, egal ob Hobbyprojekte oder Produktionen mit Millionen-Budget vom Prinzip her vollkommen gleich. Und mit diesen grundlegenden Techniken werden wir uns jetzt etwas beschäftigen.

Ablauf

Planung u. Designdokument

An erster Stelle sollte natürlich eine gute Planung stehen mit einem ausführlichem Designdokument. In Designdokument sollten wir so genau wie möglich festhalten wie unser Spiel ausschauen und ablaufen soll und wie, d.h. mit welchen Mitteln und Techniken wir das erreichen wollen. Wie man an so etwas herangehen kann, ist zum Beispiel in folgendem Artikel auf gamasutra.com ganz gut beschrieben: Creating a Great Design Document (Englisch)

Im professionellen Bereich ist ein Designdokument natürlich Pflicht, da so der Publisher einschätzen kann, was er bekommt und der Produzent weiß, was er genau produzieren soll. Es ist also sozusagen die Auftragsbeschreibung für ein Spiel von dessen Erfüllung schließlich auch die Bezahlung abhängt.

Als Hobbyentwickler ist das nicht so wichtig, aber leider nimmt es zu oft eine zu kleine Rolle ein. Wenn wir uns von vornherein einmal Gedanken zum Grundaufbau unseres Spieles machen, können wir schon frühzeitig möglicherweise auftretende Probleme erkennen und dadurch auch vermeiden. Nichts ist schlimmer als ein Code den man Monate oder Jahre bearbeitet und dann bemerkt das man eine groben Fehler im Design hat und große Teile des Codes neu schreiben muss. Ein anderer Grund ist das ein Designdokument uns auf einem gewissen Weg hält, denn zu oft gerät man in Versuchung eine plötzliche gekommene neue Idee ins Spiel einzubauen und immer weiter vom eigentlichen Inhalt des Spieles ab zukommen. Grundsätzlich ist das ja nicht schlecht, aber meistens kommt man dann zu keinem spielbaren Ergebnis mehr, und verliert leicht die Motivation das Ganze noch durch zu ziehen, gerade wenn es deutlich mehr Aufwand erfordert als erwartet.

Grafiken und Modelle

Ein kleiner Ritter in Blender

Auch wenn Konsolenspiele durchaus ihre Reize haben sprechen wir hier doch eher von Spielen, die auch stark auf die grafische Komponente setzen. Schließlich muss man ja die heutige Hardware auch ausnützen ;-) Bei diesen Spielen werden wir aber kaum um Grafiken und Modelle herum kommen. Denn durch sie bekommen die Spiele erst ihr Aussehen.

Modelle

In einer dreidimensionalen Welt werden die meisten anzutreffenden Gegenstände, Personen, Gebäude und was sonst noch alles herumsteht durch sogenannte Modelle oder manchmal auch Meshes (engl: Netz) genannt repräsentiert. Diese Modelle bestehen aus einer Ansammlung von Punkten im Raum, die Vertizes genannt werden. So ein Vertex hat immer eine Position im Raum und oft noch weitere optionale Attribute wie zum Beispiel eine Farbe, oder einen Normalvektor, der wichtig für die Beleuchtung der Modelle ist. Wenn wir jetzt jeweils drei Vertizes zu einem Dreieck oder allgemein zu einem Polygon verbinden, dann können wir damit gut Objekte in unserer 3D Welt darstellen. Da die Objekte aus vielen Polygonen aufgebaut werden, nennt man sie manchmal auch Polygonmodelle und oft wird die Qualität von Modellen auch an deren Polygonanzahl gemessen, da eine hohe Anzahl, auf eine sehr fein und genau modellierte Oberfläche hindeutet.

Da man die benötigten Daten für die Modelle nur schwer händisch generieren kann, verwendet man dafür Konstruktionsprogramme, bei denen man in einer grafischen Oberfläche den aktuellen Zustand des Modells betrachten kann um diesen dann mit den verschiedensten Werkzeugen in Echtzeit zu bearbeiten. In dem Screenshot sehen wir einen kleinen Ritter in dem kostenlos erhältlichen 3D Konstruktionsprogramm Blender. Dieses Programm wurde durch Spenden aus der Konkursmasse einer Firma aufgekauft, und steht jetzt unter einer Open-Source Lizenz kostenlos zur Verfügung. Inzwischen wurde es von vielen Freiwilligen ordentlich weiterentwickelt und übertrifft in manchen Bereichen sogar schon kommerzielle Konstruktionsprogramme, die zur zeit noch von den meisten professionellen Spieleproduzenten verwendet werden. Dabei sind die wichtigsten Modeller 3DSMax, Cinema4D und Maya. Da diese Programme aber doch sehr hohe Lizenzkosten haben und Blender schon sehr ausgereift ist, würde ich doch jedem raten es zumindest einmal mit Blender zu versuchen.

Grafiken/Texturen

Eine Asphalttextur

Da es sehr aufwendig wäre die Oberfläche aller Objekte mit farbigen Dreiecken so genau zu gestalten, dass man ein mehr oder weniger realistische Darstellung erhält verwendet man dazu sogenannte Texturen. Das sind nichts anderes als normale zweidimensionale Bilder die gedanklich auf die Modelle gewickelt werden, also zum Beispiel so wie wenn man in einem Haus eine Tapete an die Wand klebt um nicht händisch die tollen Muster an die Wand zeichnen zu müssen. Da es heute kaum mehr einen Unterschied macht ob man ein Modell mit oder ohne Texturen rendert, kann man dadurch enorme Geschwindigkeitsvorteile erzielen.

Das Problem ist nur wie man an diese Texturen kommt. Prinzipiell gibt es zwei Möglichkeiten. Man kann entweder zuerst ein sehr detailliertes Modell bauen und danach aus diesem die Texturen für ein weniger detailliertes Modell rechnen, oder man baut das Modell gleich mit dem endgültigem Detailgrad und sucht nachher die Textur für jedes Dreieck aus. Texturen kann man natürlich einerseits einfach durch fotografieren von realen Oberflächen erhalten, oder mit jedem beliebigen Zeichenprogramm händisch erstellen. Ansonsten kann sich auch noch eine Suche im Internet lohnen, da man dort auch recht viele Texturen kostenlos erhält. Rechts ist zum Beispiel eine Asphalttextur, die ich auf cgtextures.com gefunden habe.

Ein weiteres Anwendungsgebiet für Texturen ist auch die Darstellung von Schrift, für die man meistens eine Textur nimmt in der Bilder von allen Buchstaben enthalten sind. Um einen Text darzustellen zeichnet man jetzt einfach für jeden Buchstaben ein Viereck oder zwei Dreiecke auf den Bildschirm und „klebt“ die Ausschnitte der Zeichentextur mit den Bildern der jeweils benötigten Buchstaben darauf.

Programmieren

Jetzt sind wir langsam beim wirklich interessanten Teile eines jeden Spieles angelangt, nämlich dem Programmieren. Was wären denn all die schönen Modelle und Texturen wenn es dann keine Interaktivität gibt und nichts angezeigt wird :-). Um so ein Spiel programmieren zu können Bedarf es zuerst einmal einer gewissen Motivation und Interesse für dieses Thema, ansonsten können wir das gleich wieder lassen. Dann brauchen wir auch noch eine geeignete Programmiersprache. Sehr oft verwendet werden dabei C bzw. C++, da sie einerseits Hochsprachen sind, aber anderseits auch Programmieren auf sehr niedriger Ebene erlauben und dadurch dass die Programm kompiliert und nicht interpretiert werden sehr schnell laufen. Im Gegensatz zu Java, Python oder anderen interpretierten Sprachen hat man mit C++ eine großen Vorteil was die Geschwindigkeit betrifft. Da Spiele doch sehr komponentenorientiert sind schauen wir uns jetzt einmal die wichtigsten davon kurz an:

Renderer

Da normalerweise niemand der ein Spiel programmiert direkt die Grafikkarte bzw. ihren Treiber anspricht haben sich zwei große APIs entwickelt die der Kommunikation zwischen dem Spiel und der Grafikkarte dienen. Das sind einerseits OpenGL und andererseits DirectX. Bei DirectX ist der Vorteil das nicht nur eine API zum einheitlichen Ansprechen von Grafikkarten, sondern auch eine zum Verwenden von Eingabegeräten jeder Art auch mit Spezialeigenschaft wie Force-Feedback. Der große Nachteil ist das es nur eine Windowsversion gibt und damit unter Linux und anderen Plattformen nicht verwendbar ist. Deshalb würde ich sehr dazu raten OpenGL zu verwenden, da dies sowohl unter Linux als auch unter Windows verwendet werden kann. Die fehlende Schnittstelle zu den Eingabegeräten kann man leicht mit dem SDL erhalten und die Soundausgabe ebenfalls mit SDL oder auch zum Beispiel mit OpenAL, dessen Stil der API mit der von OpenGL übereinstimmt und somit für jemanden der mit OpenGL umgehen kann sehr leicht zu verwenden ist.

Wer sich nicht festlegen möchte welchen Renderer er verwenden möchte kann auch zu einer Engine greifen, die beide Renderer zur Verfügung stellt. Was eine Engine genau ist werden wir uns noch etwas später anschauen.

Gameloop

Egal mit welchen Mitteln man ein Spiel programmiert, irgendwo gibt es immer eine Schleife in der der gesamte Spielablauf vonstatten geht. Dabei kann es sein das bei manchen Bibliotheken oder Entwicklungstool diese überhaupt von uns vollkommen versteckt ist, aber vorhanden ist sie immer :) Diese Schleife, die oft als Gameloop oder Nachrichtenschleife bezeichnet wird, läuft solange das Spiel läuft auch wenn der Benutzer keine Eingaben tätigt. Und hier ist der große Unterschied zur normalen Entwicklung von Anwendungen, bei der immer auf die nächsten Eingaben vom Benutzer gewartet wird und darauf eine entsprechende Aktion durchführt. Doch jetzt werfen wir einmal einen kurzen Blick auf den möglichen Aufbau so einer Schleife:

while( Spiel nicht durch Benutzer beendet )
  Zeichne das aktuelle Bild
  Verarbeite Benutzereingaben
  Berechne KI
  Verarbeite Kollisionen
  Spiele Sound und Musik
endwhile

Bei der Reihenfolge kann es natürlich Abweichungen geben aber im groben läuft es bei fast jedem Spiel so ab. Komplizierter wird es wenn auch noch Prozessoren mit mehreren Kernen verwendet werden, aber auch da wird am grundsätzlichen Ablauf nichts geändert.

Engine

Wer nicht direkt einen der beiden Renderer verwenden möchte, der wird am besten eine Engine verwenden. Engine heißt nichts anderes als Motor und stellt einfach eine Menge Funktionen zur Verfügung, die dir Programmierung eines Spieles erleichtern. Ein Engine ist aber nicht gleich eine Engine sondern man kann mehrerer Typen unterscheiden die meistens mehrere Module haben, die gewisse Aufgaben erledigen:

Grafikengine

Eine Grafikengine ist dafür zuständig den Renderer so zu steuern, dass er die gewünschten Bilder erzeugt. Dafür gibt es meist folgende Funktionen:

  • Laden von Modellen und Texturen
  • Möglichst schnelles Rendern von Modellen (sehr wichtig zb bei großen Landschaften)
  • Spezialeffekte wie spiegelnde Oberflächen, Beleuchtung aber auch Simulation von Wasser
Physikengine

Eine Physikengine kümmert sich wie der Name schon sagt um die Physik im Spiel. Sie berechnet also zum Beispiel was passiert wenn mehrere Objekte kollidieren oder wie sich ein Fahrzeug verhält wenn es der Spieler steuert oder was passiert wenn etwas hinunterfällt. Wichtige Funktionen sind also:

  • Kollisionserkennung
  • Physikalisches Verhalten von Objekten, Fahrzeugen etc.
  • Simulation von elastischen Körpern und Flüssigkeiten (Soft body)
  • Simulation von starren Körpern (Rigid body)
Spieleengine

Schließlich gibt es auch noch jede Menge an Engines die man nicht so gut kategorisieren kann. Diese beinhalten zum Beispiel Module aus den bereits erwähnten Enginetypen oder auch zum Beispiel folgendes:

  • Soundsystem
  • Berechnung von KI
  • Netzwerksystem: Kommunikation über Netzwerke für Multiplayer
  • Skriptsprachen: Werden eingesetzt um Spielinhalt aus dem Quellcode in Skripte zu verlagern
  • Eingabeverwaltung (irgendwie muss das Spiel ja auch gesteuert werden)
  • GUI (Grafische Benutzeroberfläche)

Das war natürlich nur einmal eine kleine Auswahl an Modulen, aber was jetzt genau drinnen ist hängt immer vom Einsatzzweck der Engine ab.

Bekannte kommerzielle Engines sind die CryEngine von Crytek für FarCry und Cryis oder die Unreal Engine von Epic Games für die Unreal Reihe oder auch zum Beispiel für Tom Clancy's Rainbow Six. Da diese Engines aber sehr hohe Lizenzkosten haben ist die Opensource Gemeinde auf den Plan getreten und hat verschiedenste Engines entwickelt. An Grafikengines gibt es zum Beispiel Irrlicht oder Ogre und an Physikengines Bullet Physics, Newton Game Dynamics oder die Open Dynamics Engine. Hier ist noch als Anregung ein Screenshot einer mit Irrlich gerenderten Szene:

Eine Szene mit Irrlicht gerendert

Hier noch ein Screenshot, der zeigt was mit aktueller Hardware und dem CryEngine 2 möglich ist:

Screenshot aus Crysis mit der CryEngine 2

Natürlich muss man um ein Spiel zu programmieren keine Engine verwenden, was ich für erste Versuche auch durchaus empfehlen würde, aber wenn es einem mehr um das fertige Spiel als um das Programmieren geht, nehmen sie einem doch sehr viel Arbeit ab. Wovon ich aber dringend abraten würde ist eine eigene Engine zu programmieren nur mit dem Ziel eine Engine zu programmieren. Vor allem wenn man noch nicht viel Ahnung vom Spieleprogrammieren hat kommt dann am Ende vielleicht nur eine Engine heraus die man aufgrund eines schlechten Designs aber nicht wirklich verwenden kann. Wenn man hingegen ein Spiel ohne Engine oder aber einer Engine nur für dieses Spiel entwickelt dann hat man am Ende immerhin mindestens ein fertiges Spiel und damit in jedem Fall mehr als jemand der nur eine Engine programmiert, aber nie schafft ein Spiel damit zu entwickeln.

Spielebaukasten

Eine weitere Möglichkeit ein Spiel zu erstellen bieten noch die Spielebaukästen. Da diese nicht mehr allzu viel mit dem Programmieren von Spielen zu tun haben möchte ich sie nur mehr kurz anschneiden. Prinzipiell sind das einfach nur mehr oder weniger aufwendige grafische Oberflächen mit denen man sich Spiele zusammenklicken kann ohne zu Programmieren. Dabei kann man Objekte positionieren ihnen Eigenschaften geben und sagen wie sie gesteuert werden. Aber auch hier gibt es in der Komplexität und teilweise gibt es auch eigene Skript- und Programmiersprachen mit denen man ebenfalls den Spielverlauf beeinflussen kann. Beispiele für solche Systeme wären der GameMaker oder 3D Game Studio. Während man beim GameMaker Spiele fast nur mit der Maus erstellt, gibt es beim 3D Game Studio sogar eine eigene Programmiersprache.

Einstieg in die Programmierung

Ohne Computer

Bevor man überhaupt mit dem programmieren anfängt, sollte man sich kurz alles struktorieren und aufbauen, damit das programmieren selbst möglichst zugüg vorran geht. Es gibt einige Dinge, die zu beachten sind und einige Fragen, die man sich stellen sollte. Für diesen Prozess braucht man nichtmal einen Computer. Man könnte alles auf Stift und Papier planen. Zuerst sollte man sich darüber Gedanken machen, was für ein Spiel das ganze überhaupt wird. Man sollte sich überlegen, wozu man bereits in der Lage ist, ob es einem Möglich ist das Spiel so ohne weiteres zu vollenden. Mittendrin abzubrechen macht niemanden glücklich und am Ende seid ihr nichts weiter als heiße Luft. Vor der Spieleprogrammierung selbst könnt ihr euch ein Basisspielmodell, eine Story(falls vorhanden), die Basis der Physik im Spiel und, wie ihr die Dateien speichern/verwalten wollt, durch den Kopf gehen lassen. Dies kann man natürlich auch überspringen, allerdings würde ich dies nur für erfahrene Programmierer und auch nur bei kleinst Projekten empfehlen. Denn je mehr Gedanken man sich vorher macht, desto weniger braucht man hinterher beim Codeschreiben. Denn wenn der Code einmal steht, wer hat denn dann Lust wegen einer Fehlkalkulation den kompletten Inputteil neu zu schreiben. Dies führt zu Frustration und im schlimmsten Fall zum Projektabbruch. Also macht euch Gedanken und scheut euch auf keinen Fall „Erfahrereneren“ Fragen zu stellen, z.B. im Forum!

Ohne Engine

Wenn wir wissen möchten wie man von Grund auf ein Spiel programmiert sollten wir am Besten ohne eine Engine zu programmieren beginnen. Da wir aber nicht für jede Grafikkarte eigenen Code schreiben können werden wir aber trotzdem auf Bibliotheken zurückgreifen müssen die uns dass abnehmen. Für 3D Grafik können wir entweder OpenGL oder wenn es nur unter Windows laufen soll auch DirectX verwenden. Für einen Einstieg in die Spieleprogrammierung in 2D sind die SDL oder auch Allegro ein guter Einstieg. Die SDL kann aber auch ein OpenGL Kontext erzeugen, weshalb man mit einer Kombination aus SDL und OpenGL sehr gut Spiele mit 3D Grafik schreiben kann:

Mit (Grafik)Engine

Wollen wir uns aber nicht mit den Grundlagen abmühen sondern gleich mit dem Programmieren eines Spieles an sich, sollten wir besser eine bereits vorhanden Engine verwenden, die uns grundlegende Sachen wie das Anzeigen und Laden von Modellen, Texturen und Ähnlichem abnimmt. Vor allem im kommerziellen Bereich werden oft Lizenzen für Engines sehr teuer gekauft, aber für uns interessanter werden wohl die inzwischen zahlreich erhältlichen kostenlos verwendbaren Engines sein. Hier nur eine kurze Auflistung der wichtigsten: