Suchen und Finden
Service
Design Patterns für die Spieleprogrammierung
Robert Nystrom
Verlag mitp Verlags GmbH & Co. KG, 2015
ISBN 9783958450929 , 400 Seiten
Format PDF, ePUB, OL
Kopierschutz frei
Cover
1
Titel
3
Impressum
4
Inhaltsverzeichnis
7
Danksagungen
17
Teil I: Einführung
19
Kapitel 1: Architektur, Performance und Spiele
27
1.1 Was ist Softwarearchitektur?
27
1.1.1 Was zeichnet eine gute Softwarearchitektur aus?
28
1.1.2 Wie nimmt man Änderungen vor?
28
1.1.3 Inwiefern hilft eine Entkopplung?
30
1.2 Zu welchem Preis?
30
1.3 Performance und Geschwindigkeit
32
1.4 Das Gute an schlechtem Code
33
1.5 Ein ausgewogenes Verhältnis finden
34
1.6 Einfachheit
35
1.7 Fang endlich an!
37
Teil II: Design Patternsneu überdacht
39
Kapitel 2: Command (Befehl)
41
2.1 Eingabekonfiguration
42
2.2 Regieanweisungen
45
2.3 Rückgängig und Wiederholen
47
2.4 Klassen ohne Funktionen?
51
2.5 Siehe auch ...
53
Kapitel 3: Flyweight (Fliegengewicht)
55
3.1 Den Wald vor lauter Bäumen nicht sehen
55
3.2 Tausend Instanzen
58
3.3 Das Flyweight-Pattern
58
3.4 Ein Ort, um Wurzeln zu schlagen
59
3.5 Und die Performance?
64
3.6 Siehe auch ...
65
Kapitel 4: Observer (Beobachter)
67
4.1 Erzielte Leistungen
67
4.2 Funktionsweise
69
4.2.1 Der Observer
69
4.2.2 Das Subjekt
70
4.2.3 Beobachtung der Physik-Engine
72
4.3 »Das ist zu langsam!«
73
4.3.1 Oder ist es doch zu schnell?
74
4.4 »Zu viele dynamische Allokationen«
74
4.4.1 Verkettete Observer
75
4.4.2 Ein Pool von Listenknoten
79
4.5 Verbleibende Schwierigkeiten
79
4.5.1 Subjekte und Observer löschen
80
4.5.2 Keine Sorge, der Garbage Collector erledigt das schon
81
4.5.3 Was geht hier vor?
82
4.6 Heutige Observer
83
4.7 Zukünftige Observer
84
Kapitel 5: Prototype (Prototyp)
87
5.1 Das Design Pattern Prototype
87
5.1.1 Wie gut funktioniert es?
91
5.1.2 Spawn-Funktionen
91
5.1.3 Templates
92
5.1.4 First-Class-Typen
93
5.2 Eine auf Prototypen beruhende Sprache
93
5.2.1 Self
93
5.2.2 Wie ist es gelaufen?
96
5.2.3 Was ist mit JavaScript?
97
5.3 Prototypen zur Datenmodellierung
99
Kapitel 6: Singleton
103
6.1 Das Singleton-Pattern
103
6.1.1 Beschränkung einer Klasse auf eine Instanz
103
6.1.2 Bereitstellung eines globalen Zugriffspunkts
104
6.2 Gründe für die Verwendung
105
6.3 Gründe, die Verwendung zu bereuen
107
6.3.1 Singletons sind globale Variablen
108
6.3.2 Das Pattern löst zwei Probleme, selbst wenn es nur eins gibt
109
6.3.3 Die späte Initialisierung entzieht Ihnen die Kontrolle
110
6.4 Verzicht auf Singletons
112
6.4.1 Wird die Klasse überhaupt benötigt?
112
6.4.2 Nur eine Instanz einer Klasse
114
6.4.3 Bequemer Zugriff auf eine Instanz
115
6.5 Was bleibt dem Singleton?
118
Kapitel 7: State (Zustand)
119
7.1 Altbekanntes
119
7.2 Zustandsautomaten erledigen das
123
7.3 Enumerationen und Switch-Anweisungen
124
7.4 Das State-Pattern
127
7.4.1 Das Interface für den Zustand
128
7.4.2 Klassen für alle Zustände
128
7.4.3 An den Zustand delegieren
129
7.5 Wo sind die Zustandsobjekte?
130
7.5.1 Statische Zustände
130
7.5.2 Instanziierte Zustandsobjekte
131
7.6 Eintritts- und Austrittsaktionen
132
7.7 Wo ist der Haken?
134
7.8 Nebenläufige Zustandsautomaten
134
7.9 Hierarchische Zustandsautomaten
136
7.10 Kellerautomaten
138
7.11 Wie nützlich sind sie?
139
Teil III: Sequenzierungsmuster (Sequencing Patterns)
141
Kapitel 8: Double Buffer (Doppelter Buffer)
143
8.1 Motivation
143
8.1.1 Computergrafik kurz und bündig
143
8.1.2 Erster Akt, erste Szene
145
8.1.3 Zurück zur Grafik
146
8.2 Das Pattern
146
8.3 Anwendbarkeit
147
8.4 Konsequenzen
147
8.4.1 Der Austausch selbst kostet Zeit
147
8.4.2 Zwei Framebuffer belegen mehr Arbeitsspeicher
147
8.5 Beispielcode
148
8.5.1 Nicht nur Grafik
151
8.5.2 Künstliche Unintelligenz
151
8.5.3 Gebufferte Ohrfeigen
155
8.6 Designentscheidungen
156
8.6.1 Wie werden die Buffer ausgetauscht?
157
8.6.2 Wie fein ist der Buffer untergliedert?
158
8.7 Siehe auch ...
159
Kapitel 9: Game Loop (Hauptschleife)
161
9.1 Motivation
161
9.1.1 Interview mit einer CPU
161
9.1.2 Ereignisschleifen
162
9.1.3 Eine aus dem Takt geratene Welt
163
9.1.4 Sekunden pro Sekunde
164
9.2 Das Pattern
164
9.3 Anwendbarkeit
164
9.4 Konsequenzen
165
9.4.1 Abstimmung mit der Ereignisschleife des Betriebssystems
165
9.5 Beispielcode
166
9.5.1 Die Beine in die Hand nehmen
166
9.5.2 Ein kleines Nickerchen
166
9.5.3 Ein kleiner und ein großer Schritt
167
9.5.4 Aufholjagd
169
9.5.5 In der Mitte hängen geblieben
171
9.6 Designentscheidungen
173
9.6.1 Stammt die Game Loop aus Ihrer Feder oder benutzen Sie die der Plattform?
173
9.6.2 Wie handhaben Sie die Leistungsaufnahme?
174
9.6.3 Wie steuern Sie die Spielgeschwindigkeit?
175
9.7 Siehe auch ...
176
Kapitel 10: Update Method (Aktualisierungsmethode)
177
10.1 Motivation
177
10.2 Das Pattern
180
10.3 Anwendbarkeit
180
10.4 Konsequenzen
181
10.4.1 Verkomplizierung durch Aufteilen des Codes in einzelne Frames
181
10.4.2 Der Zustand muss gespeichert werden, um im nächsten Frame fortfahren zu können
181
10.4.3 Alle Objekte simulieren jeden Frame, aber nicht wirklich exakt gleichzeitig
182
10.4.4 Obacht bei der Modifizierung der Objektliste während der Aktualisierung
182
10.5 Beispielcode
184
10.5.1 Entity-Unterklassen?
186
10.5.2 Entities definieren
186
10.5.3 Zeitablauf
189
10.6 Designentscheidungen
190
10.6.1 Zu welcher Klasse gehört die update()-Methode?
190
10.6.2 Wie werden inaktive Objekte gehandhabt?
191
10.7 Siehe auch ...
192
Teil IV: Verhaltensmuster (Behavioral Patterns)
193
Kapitel 11: Bytecode
195
11.1 Motivation
195
11.1.1 Wettkampf der Zaubersprüche
196
11.1.2 Daten > Code
196
11.1.3 Das Interpreter-Pattern
196
11.1.4 Faktisch Maschinencode
200
11.2 Das Pattern
201
11.3 Anwendbarkeit
201
11.4 Konsequenzen
201
11.4.1 Befehlsformat
202
11.4.2 Fehlender Debugger
203
11.5 Beispielcode
203
11.5.1 Eine zauberhafte API
203
11.5.2 Ein bezaubernder Befehlssatz
204
11.5.3 Eine Stackmaschine
206
11.5.4 Verhalten = Komposition
209
11.5.5 Eine virtuelle Maschine
212
11.5.6 Hexerwerkzeuge
213
11.6 Designentscheidungen
215
11.6.1 Wie greifen Befehle auf den Stack zu?
215
11.6.2 Welche Befehle gibt es?
216
11.6.3 Wie werden Werte repräsentiert?
217
11.6.4 Wie wird der Bytecode erzeugt?
220
11.7 Siehe auch ...
222
Kapitel 12: Subclass Sandbox (Unterklassen-Sandbox)
223
12.1 Motivation
223
12.2 Das Pattern
225
12.3 Anwendbarkeit
226
12.4 Konsequenzen
226
12.5 Beispielcode
226
12.6 Designentscheidungen
229
12.6.1 Welche Operationen sollen bereitgestellt werden?
229
12.6.2 Sollen Methoden direkt oder durch Objekte, die sie enthalten, bereitgestellt werden?
231
12.6.3 Wie gelangt die Basisklasse an die benötigten Zustände?
232
12.7 Siehe auch ...
236
Kapitel 13: Type Object (Typ-Objekt)
237
13.1 Motivation
237
13.1.1 Die typische OOP-Lösung
237
13.1.2 Eine Klasse für eine Klasse
239
13.2 Das Pattern
241
13.3 Anwendbarkeit
241
13.4 Konsequenzen
242
13.4.1 Typ-Objekte müssen manuell gehandhabt werden
242
13.4.2 Die Definition des Verhaltens der verschiedenen Typen ist schwieriger
242
13.5 Beispielcode
243
13.5.1 Typartiges Verhalten von Typ-Objekten: Konstruktoren
245
13.5.2 Gemeinsame Nutzung von Daten durch Vererbung
246
13.6 Designentscheidungen
250
13.6.1 Ist das Typ-Objekt gekapselt oder zugänglich?
250
13.6.2 Wie werden Typ-Objekte erzeugt?
251
13.6.3 Kann sich der Typ ändern?
252
13.6.4 Welche Formen der Vererbung werden unterstützt?
253
13.7 Siehe auch ...
254
Teil V: Entkopplungsmuster (Decoupling Patterns)
255
Kapitel 14: Component (Komponente)
257
14.1 Motivation
257
14.1.1 Der Gordische Knoten
258
14.1.2 Den Knoten durchschlagen
258
14.1.3 Unerledigtes
259
14.1.4 Wiederverwendung
259
14.2 Das Pattern
261
14.3 Anwendbarkeit
261
14.4 Konsequenzen
262
14.5 Beispielcode
262
14.5.1 Eine monolithische Klasse
263
14.5.2 Abspalten eines Bereichs
264
14.5.3 Abspalten der übrigen Bereiche
266
14.5.4 Robo-Bjørn
268
14.5.5 Ganz ohne Bjørn?
270
14.6 Designentscheidungen
272
14.6.1 Wie gelangt ein Objekt an seine Komponenten?
273
14.6.2 Wie kommunizieren die Komponenten untereinander?
273
14.7 Siehe auch ...
277
Kapitel 15: Event Queue (Ereigniswarteschlange)
279
15.1 Motivation
279
15.1.1 Ereignisschleife der grafischen Benutzeroberfläche
279
15.1.2 Zentrale Ereignissammlung
280
15.1.3 Wie bitte?
281
15.2 Das Pattern
284
15.3 Anwendbarkeit
284
15.4 Konsequenzen
285
15.4.1 Eine zentrale Ereigniswarteschlange ist eine globale Variable
285
15.4.2 Den Boden unter den Füßen verlieren
285
15.4.3 Steckenbleiben in Rückkopplungsschleifen
286
15.5 Beispielcode
286
15.5.1 Ein Ring-Buffer
289
15.5.2 Anfragen zusammenfassen
293
15.5.3 Threads
294
15.6 Designentscheidungen
295
15.6.1 Was soll in die Warteschlange aufgenommen werden?
295
15.6.2 Wer darf lesend auf die Warteschlange zugreifen?
296
15.6.3 Wer darf schreibend auf die Warteschlange zugreifen?
298
15.6.4 Wie lang ist die Lebensdauer der Objekte in der Warteschlange?
299
15.7 Siehe auch ...
300
Kapitel 16: Service Locator (Dienstlokalisierung)
301
16.1 Motivation
301
16.2 Das Pattern
302
16.3 Anwendbarkeit
302
16.4 Konsequenzen
303
16.4.1 Der Dienst muss auch tatsächlich lokalisiert werden können
303
16.4.2 Dem Dienst ist nicht bekannt, wer ihn nutzt
303
16.5 Beispielcode
304
16.5.1 Der Dienst
304
16.5.2 Der Dienstanbieter
304
16.5.3 Ein einfacher Service Locator
305
16.5.4 Ein leerer Dienst
306
16.5.5 Protokollierender Dekorierer
308
16.6 Designentscheidungen
310
16.6.1 Wie wird der Dienst lokalisiert?
310
16.6.2 Was geschieht, wenn die Lokalisierung des Dienstes scheitert?
312
16.6.3 Wer darf auf den Dienst zugreifen?
315
16.7 Siehe auch ...
316
Teil VI: Optimierungsmuster (Optimization Patterns)
317
Kapitel 17: Data Locality (Datenlokalität)
319
17.1 Motivation
319
17.1.1 Ein Datenlager
320
17.1.2 Eine Palette für die CPU
322
17.1.3 Daten = Performance?
323
17.2 Das Pattern
324
17.3 Anwendbarkeit
325
17.4 Konsequenzen
325
17.5 Beispielcode
326
17.5.1 Aneinandergereihte Arrays
326
17.5.2 Gebündelte Daten
331
17.5.3 Hot/Cold Splitting
335
17.6 Designentscheidungen
337
17.6.1 Wie wird Polymorphismus gehandhabt?
338
17.6.2 Wie werden Spielobjekte definiert?
339
17.7 Siehe auch ...
342
Kapitel 18: Dirty Flag (Veraltet-Flag)
345
18.1 Motivation
345
18.1.1 Lokale Koordinaten und Weltkoordinaten
346
18.1.2 Gecachete Weltkoordinaten
347
18.1.3 Verzögerte Berechnung
348
18.2 Das Pattern
350
18.3 Anwendbarkeit
350
18.4 Konsequenzen
351
18.4.1 Nicht zu lange verzögern
351
18.4.2 Das Flag bei jedem Zustandswechsel ändern
352
18.4.3 Vorherige abgeleitete Daten verbleiben im Speicher
352
18.5 Beispielcode
353
18.5.1 Nicht-optimierte Traversierung
354
18.5.2 Let’s Get Dirty
355
18.6 Designentscheidungen
358
18.6.1 Wann wird das Dirty Flag gelöscht?
358
18.6.2 Wie feingranular ist Ihr »Dirty-Tracking«?
359
18.7 Siehe auch ...
360
Kapitel 19: Object Pool (Objektpool)
361
19.1 Motivation
361
19.1.1 Der Fluch der Fragmentierung
361
19.1.2 Das Beste beider Welten
362
19.2 Das Pattern
363
19.3 Anwendbarkeit
363
19.4 Konsequenzen
363
19.4.1 Der Pool verschwendet möglicherweise Speicherplatz für ungenutzte Objekte
363
19.4.2 Es steht nur eine feste Anzahl von Objekten zur Verfügung
364
19.4.3 Die Objekte sind von fester Größe
365
19.4.4 Wiederverwendete Objekte werden nicht automatisch zurückgesetzt
365
19.4.5 Unbenutzte Objekte verbleiben im Arbeitsspeicher
366
19.5 Beispielcode
366
19.5.1 Eine kostenlose Liste
369
19.6 Designentscheidungen
372
19.6.1 Sind Objekte an den Pool gekoppelt?
372
19.6.2 Wer ist für die Initialisierung der wiederverwendeten Objekte verantwortlich?
374
19.7 Siehe auch ...
376
Kapitel 20: Spatial Partition (Räumliche Aufteilung)
377
20.1 Motivation
377
20.1.1 Kampfeinheiten auf dem Schlachtfeld
377
20.1.2 Schlachtreihen zeichnen
378
20.2 Das Pattern
379
20.3 Anwendbarkeit
379
20.4 Konsequenzen
379
20.5 Beispielcode
380
20.5.1 Ein Bogen Millimeterpapier
380
20.5.2 Ein Gitternetz verketteter Einheiten
381
20.5.3 Betreten des Schlachtfeldes
383
20.5.4 Klirrende Schwerter
384
20.5.5 Vormarschieren
385
20.5.6 Um Armeslänge
386
20.6 Designentscheidungen
390
20.6.1 Ist die Aufteilung hierarchisch oder gleichmäßig?
390
20.6.2 Hängt die Zellengröße von der Verteilung der Objekte ab?
391
20.6.3 Werden die Objekte nur in den Zellen gespeichert?
393
20.7 Siehe auch ...
394
Stichwortverzeichnis
395