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!
© Copyright 2025 ExpyDoc