Vielleicht erstmal ein paar puristische Merksätze:
- Ein gutes Klassenkonzept braucht immer Vorplanung und den Mut zur
Neuimplementation, wenn man merkt, dass man etwas vergessen hat.
- Der Untergang eines guten Klassenkonzeptes ist Flickschusterei.
- Wenn man Probleme beim Erkennen der Klassenhierarchie hat, ist der Ansatz falsch.
Keine Ahnung, ob man diese Sätze so in Lehrbüchern findet, aber es sind
die, welche ich mir immer aufbete, wenn es an die Kreation einer neuen
Klassenhierarchie geht.
Allerdings bin ich auch so frei, Klassen nur dort einzusetzen, wo es
locker von der Hand geht, sobald etwas mit Klassen mühsam wird, kommen
bei mir wieder offene C-Strukturen zum Einsatz.
Aber bei einem Spiel fällt doch eine Klasse sofort in's Gesicht, das
Spielobjekt. Es hat gewisse Eigenschaften und man kann etwas damit
machen. Was man damit machen kann, sind bei C++ die Methoden, wie z.B.
Aufnehmen, Ablegen, Benutzen oder Darstellen. Sicher ist es auch keine
schlechte Idee, Methoden zur Serialisierung mit aufzunehmen, damit man
das Objekt auch speichern kann. Angereichert mit ein paar globaleren
Dingen wie Szene initialisieren und Szene verlassen ist diese Klasse
schonmal fertig.
Aber so einfach sich das auch anhört, der Teufel steckt natürlich im
Detail. Wie verwaltet man denn solche Objekte? Nur ein Array davon
hilft nicht weiter, wenn man z.B. etwas auf einem Sand-Objekt ablegen
möchte. Ausserdem sollte das Objekt unterscheiden können, ob der Held
oder jemand anderes drüberläuft.
Apropos Laufen. Es ist sicher eine gute Idee, bewegende und
nicht-bewegende Objekte unterschiedlich zu implementieren, da diese nur
wenig gemeinsame Eigenschaften aufweisen werden, vielleicht mit
Ausnahme der Anzeige und der Serialisierung. Vielleicht gibt's auch
eine gemeinsame Basis-Klasse, welche diese beiden Dinge implementiert.
Du solltest Dir vor allem auch einmal Gedanken über die
Speicherverwaltung machen. Tonnenweise new und delete Operatoren sorgen
in den üblichen Applikationen für die meisten Probleme. Ich persönlich
vermeide dynamische Speicherobjekte, wenn ich sie nicht unbedingt
brauche.
Daher ist bei Robot
die Interpretation der Klassen auch eine ganz andere, als man es
erwarten würde. Sicher, es gibt eine Objekt-Klasse die der oben
beschriebenen stark ähnelt. Jedes Objekt in Robot ist eine Spezialisierung dieser Basisklasse.
Allerdings werden von diesen Klassen keine dynamischen Instanzen
erzeugt, vielmehr existiert von jeder Objektklasse genau eine Instanz,
welche während der Programminitialisierung erzeugt wird.
Das eigentliche "Objekt" im Spiel, ist letztendlich nur noch ein
16-Bit-Wert, der in den unteren 8 Bit den Objekt-Typ definiert und die
oberen 8 Bit für Attribute zur Verfügung stellt. Diese oberen 8 Bit
definieren z.B. wie ein Tangram-Teil aussieht, ob ein Waldstück
begehbar ist oder wieviele Streichhölzer noch in der Packung sind.
Die Objekte sind dann stur in einem 2D-Array abgelegt, welches so die
eigentliche Szene definiert. Wenn irgendwo etwas hingelegt wird, setze
ich im Array einfach nur den Wert hinein, nehme ich etwas weg, setze
ich den Wert auf 0. Ohne jegliche Allokation.
Wenn ich mit einem Objekt etwas anfangen möchte, rufe ich die jeweilige
Methode der Objekt-Instanz auf, die Zuordnung erfolgt dabei über ein
(ebenfalls statisches) Array von Zeigern auf die Objekt-Instanzen mit
den unteren 8Bit meines Objekt-Wertes als Index.
Probleme mit dem Speichern oder Duplizieren habe ich dadurch auch
nicht, einfach das Array wegkopieren oder eben den Wert zusätzlich
woanders hinspeichern.
Wie gesagt: Wenn bei der Realisierung etwas Kopfschmerzen bereitet,
sollte man es anders lösen. Meist gibt es eine Variante, bei der sich
alle Probleme in Luft auflösen.
Ich hoffe dass das etwas weiter hilft... 😉