Game Programming Patterns

Game Programming Patterns
ROBERT NYSTROM
Yvonne Schröer am 25.06.2015
Softwaretechnologie II (Teil 2):
Simulation und 3D Programmierung
Table of Contents
I. Introduction
1.
Architecture, Performance, and Games
II. Design Patterns Revisited
2.
Command
I. Introduction
Das Problem:
Je größer ein Programm bzw. Spiel ist, desto unübersichtlicher/chaotischer
wird der Code.
→ Einbußen bei Laufzeit-Performanz, Code wird schwieriger zu
verstehen/bearbeiten/erweitern.
Frage:
Wie organisiert man Programme? Wie sollte die interne Architektur eines
Spieles aussehen?
→ Autor präsentiert aufgearbeitete Designmuster aus Spielen.
WHAT‘S IN STORE
Warum noch ein Buch über Gameprogrammierung?
Domänen-spezifische Bücher.
Befassen sich nur mit einem kleinen, sehr spezifischen Teil der
Gameprogrammierung (z.B. KI).
Ganze-Engine Bücher.
Befassen sich mit verschiedenen Teilen einer ganzen Engine, die auf eine
bestimmte Art Spiel ausgerichtet ist (z.B. 3D First Person Shooter).
→ Nystrom möchte voneinander unabhängige Ideen
präsentieren, die auf den eigenen Code angewendet werden
können: Mix & Match Prinzip
HOW IT RELATES TO DESIGN PATTERNS
Design Patterns: Elements of Reusable Object-Oriented Software
Buch, das sich als einer der ersten mit Designmustern für Software befasst hat.
„Design Patterns“ anwendbar auf game software
↕
„Game Programming Patterns“ anwendbar auf non-game software
Aber: „Game Programming Patterns“ bezieht sich besonders auf übliche
Herausforderungen in der Gameprogrammierung!




Zeit & Ablauf
Komprimierte Entwicklungszyklen
Interaktionen
Performanz
HOW TO READ THE BOOK
Drei Hauptteile:
1.
2.
3.
Einführung
Design Patterns Revisited: Muster aus „Design Patterns“
13 nützliche Designmuster, in 4 Kategorien unterteilt
Jedes vorgestellte Designmuster behandelt folgende Gesichtspunkte:







Intent
Motivation
Pattern
When To Use It & Keep In Mind
Sample Code
Design Decisions
See Also
ABOUT THE SAMPLE CODE
Code Beispiele sind in C++, da Lingua Franca der Gamesindustrie.
Muster aber auch übertragbar auf syntaxähnliche und/oder objektorientierte
Programmiersprachen wie Java, C#, JavaScript, etc.
Code ist einfach und verständlich gehalten; daher teilweise „schlechter“ C++ Code.
Um Platz zu sparen, wird Code irrelevant für das Designmuster ausgelassen.
Beispiel:
bool update()
{
// Do work...
return isDone();
}
1. Architecture, Performance, and Games
WHAT IS SOFTWARE ARCHITECTURE?
Fokus auf Code organisieren, statt auf Code schreiben.
Zentrale Frage:
Wie unterscheiden wir
gute Software-Architektur von schlechter?
WHAT IS GOOD SOFTWARE ARCHITECTURE?
Gute Software-Architektur wird daran gemessen,
wie anpassungsfähig (Änderungen, Erweiterungen) sie ist!
HOW DO YOU MAKE A CHANGE?
1.
Bevor man Features hinzufügen kann, muss der vorhandene Code verstanden werden.
2.
Dann wird der neue Code hinzugefügt, wenn man einen Lösungsansatz hat.
3.
Zum Schluss wird der gesamte Code aufgeräumt (clean up).
HOW CAN DECOUPLING HELP?
Codeteile sind oft miteinander gekoppelt bzw. voneinander abhängig → man muss viel zu viel Code
in sein Gehirn „laden“, bevor man am Code arbeiten kann!
Ziel:
Codeteile voneinander abkoppeln, sodass
→ weniger Code gelernt werden muss,
→ Änderungen an einem Codeteil keine Änderungen
in anderen Codeteilen voraussetzt.
„minimize the amount of knowledge you need to have
in-cranium before you can make progress“
AT WHAT COST?
Abkoppeln von Codeteilen führt langfristig zu mehr Übersicht und Produktivität!
Aber vorsicht!
Der Umfang und die Absicht des Projekts immer bedacht werden, sonst werden zuviele
„extension points“ hinzugefügt, die man niemals braucht!
Es wird mehr Zeit damit verbracht
ein Codegrundgerüst zu schreiben,
statt Code, der tatsächlich etwas macht!
PERFORMANCE AND SPEED
Kritik:
Zu viele verschiedene Designmuster, die das Spiel flexibel und erweiterbar machen,
beeinträchtigen die Performanz → „…and other mechanisms, that all have at least
some runtime cost“.
Optimieren heißt Limits setzen.
Aber Flexibilität fördert die Entwicklungsgeschwindigkeit
(Balancing, Prototyping).
Kompromiss:
Während der Entwicklung den Code weitgehend flexibel gestalten, und erst am Ende optimieren.
THE GOOD IN BAD CODE
Ziel: Sauberer, eleganter Code, für eine durchgängig gute Software-Architektur
Aber: Game Design erfordert Experimentieren
Schlechter, „zusammengeschmissener“ Code ist akzeptabel für Prototyping und eine legitime
Programmierpraxis, aber es muss sichergestellt werden, dass er nicht in das Endprodukt
übernommen wird!
Schlechte Manager…
→ NEIN!!!
STRIKING A BALANCE
Was wir wollen:
1.
2.
3.
Gute, übersichtliche Software-Architektur
Optimale Laufzeit-Performanz
Schnelles Implementieren von Features
Die Ziele stehen teilweise im Widerspruch zueinander; zum Beispiel steigert gute SoftwareArchitektur langfristig die Produktivität, nimmt selber aber auch viel Zeit in Anspruch.
Es gibt hier keine einheitliche Antwort oder Strategie!
Genau wie verschiedene Spiele verschiedene Strategien zum Gewinnen benötigen, braucht auch
ein Spiel-Projekt seine eigene Herangehensweise bei der Entwicklung.
SIMPLICITY
Code so simpel wie möglich halten → bedeutet nicht zwangsweise weniger Arbeit!
Denn: wir werden nur selten mit einem „eleganten“ und einfachem Problem konfrontiert.
In der Regel haben wir eine große Anzahl von verschiedenen Use Cases, die alle abgedeckt werden
wollen…
…ohne dass wir für jeden separaten Fall eine eigene Codelogik schreiben.
Simpler Code heißt: einen generellen Code finden, der soviele Use Cases wie möglich abdeckt!
„Finding that is a bit like pattern matching or solving a puzzle.“
GET ON WITH IT, ALREADY
Zusammengefasst:
 Abstraktion und Abkoppeln macht den Code flexibler und einfacher, aber stelle sicher,
dass du diese spezifische Flexibilität auch benötigst.
 Behalte Laufzeit-Performanz stets im Hinterkopf während der Entwicklung, aber
verschiebe kleinere Optimierungsprozesse an den Schluss.
 Designe und implementiere zügig, aber hinterlasse kein Codechaos dabei.
 Verschwende keine Zeit damit, schönen Code zu produzieren, wenn du weißt, dass du ihn
wegschmeißt.
 „But, most of all, if you want to make something fun, have fun making it.“
II. Design Patterns Revisited
Design Patterns: Elements of Reusable Object-Oriented Software
Fast 20 Jahre alt, aber immer noch relevant! Spricht für zeitloses Design?
Muster die behandelt werden:






Command
Flyweight
Observer
Prototype
Singleton
State
2. Command
Command ist ein nützliches, oft vorkommendes Muster.
„A command is a reified method call.“
→ Ein vergegenständlichter Methodenaufruf.
„[…] taking some concept and turning it into a piece of data – an
object – that you can stick in a variable, pass to a function, etc. […]
what I mean is that it‘s a method call wrapped in an object.“
CONFIGURING INPUT
Ein Beispiel
↓
void InputHandler::handleInput()
{
if (isPressed(BUTTON_X)) jump();
else if (isPressed(BUTTON_Y)) fireGun();
else if (isPressed(BUTTON_A)) swapWeapon();
else if (isPressed(BUTTON_B)) lurchIneffectively();
}
Button Layout konfigurieren?!
Jump() & fireGun() austauschen
für Objekte, die eine bestimmte Aktion
repräsentieren.
→ Command Muster
CONFIGURING INPUT
1. Definiere Basisklasse für triggerbare Anweisung
class Command
{
public:
virtual ~Command() {}
virtual void execute() = 0;
};
2. Definiere Unterklassen für verschiedene Game Aktionen
3. Im Input Handler Zeiger auf Befehl für die einzelnen Tasten
class InputHandler
{
public:
void handleInput();
// Methoden um Befehle zu binden…
private:
Command* buttonX_;
Command* buttonY_;
Command *buttonA_;
Command* buttonB_;
};
class JumpCommand : public Command
{
public:
virtual void execute() { jump(); }
};
class FireCommand : public Command
{
public:
virtual void execute() { fireGun(); }
};
// etc…
4. Jetzt verweist das Input Handling nur auf die Zeiger
void InputHandler::handleInput()
{
if (isPressed(BUTTON_X)) buttonX_->execute();
else if (isPressed(BUTTON_Y)) buttonY_->execute();
else if (isPressed(BUTTON_A)) buttonA_->execute();
else if (isPressed(BUTTON_B)) buttonB_->execute();
}
Vorher hat jeder Tastendruck direkt eine Funktion aufgerufen, jetzt gibt es einen Umweg.
Das Kernprinzip des Command Musters.
QUELLEN
Robert Nystrom; gameprogrammingpatterns.com
Vielen Dank für die Aufmerksamkeit!