Was ist der richtige objektorientierte Ansatz für das Klassendesign in der Spieleentwicklung?


31

Ich bin gerade dabei, ein 2D-Sprite-basiertes Spiel für Windows 7 Phone mit XNA zu entwickeln. Die dafür verfügbaren Schulungen und Tutorials sind ziemlich hilfreich, aber das Problem, dem ich gegenüberstehe, ist, dass jeder von ihnen anders an sein Klassendesign herangeht und der Code nicht besonders gut faktorisiert ist. Infolgedessen war es für mich schwierig, genau zu verstehen, welche Aufgaben ich einer bestimmten Klasse übertragen sollte.

Zum Beispiel könnte ich eine Basis-Sprite-Klasse haben BaseSprite, die weiß, wie sie sich selbst zeichnet, auf Kollisionen prüft usw. Dann könnte ich eine AnimatedSpriteKlasse haben, die weiß, wie sie in ihrem Sprite-Sheet, einer ExplodingSpriteKlasse usw. navigiert . Diese Technik wird im Space Invaders-Beispiel in den Materialien zu Windows 7 Phone Jumpstart Session 2 demonstriert .

Alternativ könnte ich stattdessen den Großteil des Renderns und Ausführens der Spielverantwortung in eine GameScreenKlasse einordnen. Diese Klasse und ihre abgeleiteten Klassen verhalten sich in Bezug auf ihre Zuständigkeiten eher wie Formulare oder Webseiten. Sprite-Klassen sind einfachere Container mit viel weniger Logik.

Dies ist die Technik, die im Alien Sprite-Spiel des Windows 7 Phone Training Kits und in anderen Beispielen für den Spielstatus-Manager verwendet wird.

Was ist der richtige objektorientierte Ansatz für das Klassendesign in der Spieleentwicklung?

Antworten:


26

Ich benutze einen komponentenorientierten Ansatz, bei dem Sie eine Sprite-Klasse mit Komponenten wie Visual, Collision, Animation, Input usw. haben. Bei diesem Ansatz habe ich keine tiefe Klassenhierarchie (was gut ist). .

Weitere Informationen zum komponentenorientierten Design finden Sie hier .


2
+1 Der Artikel, mit dem Sie verlinkt haben, war fantastisch. Ich habe mich so sehr auf das reine OO-Design konzentriert, dass ich das Modell vom Typ Bauteil / Dekorateur völlig übersehen habe.
Josh E

1
Das Komponentenmuster ist nicht wirklich "weniger rein" OO :)
Srekel

2
Tatsächlich. OO wird oft mit Vererbung gleichgesetzt. Aber Vererbung ist nur ein Werkzeug, das OO anbietet, Zusammensetzung ist ein anderes.
haffax

Einfach so. Ich hätte präziser formulieren sollen; Was ich damit meinte, war, dass ich mich zu sehr auf die Vererbungsseite von OO konzentrierte, anstatt an OO-Entwurfsmuster und andere OO-Aspekte zu denken, die mir helfen könnten, das zu erreichen, was ich wollte.
Josh E

Während ein auf Komositionen basierender Ansatz ziemlich offensichtlich ist und häufig verwendet wird, muss ich noch eine Lösung finden, um die Rendering-Komponente portabel zu halten. Irgendwelche Tipps wären toll.
Andreas


6

Die SOLID-Prinzipien gelten für das Design von Spielecodes genauso wie für jeden anderen Beruf - zumindest bis zur Optimierung. Daher würde ich Ihr erstes Beispiel als Ausgangspunkt nehmen.

Ich würde jedoch noch weiter gehen, da BaseSprite so klingt, als würde es zu einer Megaklasse werden. Das Prinzip der Einzelverantwortung schreibt vor, dass Kollision, Rendering und Navigation von Komponenten und nicht von einzelnen Einträgen in einer Klassenhierarchie behandelt werden sollen. Die Halteklasse all dieser Komponenten sollte nur mit dem Verschieben von Weltpositionen zwischen ihnen umgehen.


5

Bei den letzten Projekten habe ich mich mehr auf einen MVC-Ansatz konzentriert.

Zuerst waren wir uns nicht sicher, ob das funktionieren würde, aber es hat perfekt funktioniert.

Modell

Die Datenobjekte. Nur die reinen Daten. Kein Verhalten, kein Rendern.

Datenmanager. Nur mit "Listen" von Datenobjekten umgehen. (Kann auch erweitert werden, um das Pooling zu unterstützen.)

Aussicht

Wir nennen sie Renderer. Für jeden Datenobjekttyp gibt es einen Renderer. Wenn es mit einem Manager aufgerufen wird, werden alle Objekte in dieser Liste gerendert.

Regler

Entspricht den Renderern, steuert jedoch das Verhalten.

Beispiel

Der ShipManager verfügt über eine Liste von Schiffen. Der ShipController verschiebt die Schiffe entsprechend ihrem Status. Der ShipRenderer rendert die Schiffe entsprechend ihrem Status.

Warum

Auf diese Weise sind Sicht und Logik streng voneinander getrennt. Es macht das Portieren auf eine neue Plattform ziemlich einfach. Die Optimierung des Datenlayouts im XxxManager ist ebenfalls sehr einfach.


2
Ich stimme ab, weil ich es satt habe, "Use MVC" als akzeptable Antwort zu sehen. Wenn Sie auf einer modernen Plattform entwickeln, verwenden Sie MVC bereits auf mehreren Ebenen. Es ist keine spezifische Antwort und es ist keine gute Antwort, da es den Leuten nicht sagt, wie sie Klassen strukturieren sollen, was aufgaben- / domänenspezifisch ist. Am Ende schreiben viele Leute "class Modal ...; class View ...; class Controller ..." MVC ist ein Muster mit vielen guten Erklärungen, wenn es um vorhandenen Code geht. Es ist kein Muster mit viel guter Planungskraft.

4
@ Joe Ich verstehe, aber finde deine Wortwahl unnötig unhöflich. Ich habe nur erklärt, wie wir es machen. Da die Architekturauswahl auf höherer Ebene die Designauswahl auf niedrigerer Ebene überflüssig macht, halte ich sie für eine gültige Antwort.
Andreas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.