Ich bau drauflos und betreibe kräftiges Refactoring, wenn sich der Bedarf dafür herausstellt.
Jup, genau so!
Mein Hauptproblem ist natürlich, dass ich jetzt noch nicht weiß, wie genau das fertige Spiel aussehen wird. Andererseits finde ich es gerade lohnend, wenn man ein Spiel anfängt und so lange Stärken ausbaut, bis etwas tolles dabei entsteht. Welchen Sinn hat es, ein Spiel von vorne bis hinten zu planen, wenn ich noch nicht weiß, wie sich die Mechanik hinterher anfühlt und welche Stärken oder Schwächen sie hat?
Wenn man also schon das Spiel nicht von vorne bis hinten planen kann, dann auch nicht den Code.
Aber selbst wenn man genau weiß, was man coden wird, kommt man um Refactoring kaum herum. Wenn ich irgendein Problem angehe, habe ich meistens im Kopf eine Vorstellung davon, wie es funktionieren wird, welche Klassen es gibt, wie diese zusammen spielen und so weiter. Die grundsätzliche Idee ist auch ansich immer ok, Fehler kommen im Detail. Da schreibt man 5 Zeilen Code und merkt, dass eine davon Dinge benötigt, an die du einfach nicht rankommst. Per Design. Also musst du das Design ändern. Das ein Design auf hoher Ebene zu funktionieren scheint, ist schnell klar, aber für manche Dinge müsste man eben so detailliert planen, dass man es im Grunde auf dem Papier schon programmiert hat. Dann programmiere ich doch lieber direkt, und kann zwischendrin testen.
Wichtig bei allen Umbaumaßnahmen: Immer auf sauberen und strukturierten Code achten. Keine fiesen Hacks einbauen (außer zu Testzwecken). Ich achte immer darauf, dass mein Code eine logische Idee hat und möglichst robust ist. Das klingt ziemlich vage, und ist es wohl irgendwie auch. Vermutlich kommt das erst mit der Erfahrung. Aber vielleicht lässt es sich damit zusammenfassen: Sorge dafür das auch der größte Idiot deinen Code nicht falsch benutzen kann, bzw. es wenigstens auf jeden Fall merkt. Weil eben jener ist man selber.
Vielleicht mal ein Beispiel. Früher hatte ich eine Klasse, die alle Gegner gemanagt hat. Pro Typ einen Manager. Irgendwann kam ich dahinter, dass Gegner eigentlich gleich Gegner sind, und ich mit etwas generischen Code mit einem einzigen Manager auskomme.
Später kam ich dann auf die Idee, das man auch den Spieler und sonstige Objekte in gewisser Weise genauso wie die Gegner behandeln kann. Also gab es eine Charakter-Oberklasse, und abgeleitete Klasse für Spieler und diverse Gegnertypen.
Dann habe ich gemerkt, dass statische Typen eigentlich doof sind. Was ist, wenn ich mal in die Haut eines Gegners schlüpfen möchte um ihn zu steuern? Aslo war ein Gegner keine Abgeleitete Klasse mehr, sondern ein Charakter, der einen AI-Kontroller hat. Diese kann ich durch einen Player-Kontroller ersetzen und schon kann ich den Gegner als Spieler steuern.
Mittlerweile ist daraus ein Entity-System geworden, bei dem alles was in der Welt rumsteht ein Entity ist und verschiedene Componenten hat. Diese sorgen zum Beispiel für Kollisionsabfrage, oder geben einem Gebäude die Fähigkeiten, Güter zu produzieren. Durch ein Eventsystem können Componenten auf Dinge wie "Entity wird gerender" oder "Entity ändert seine Position" reagieren.
Aber: Man kann alles auch übertreiben, leider. Festgestellt habe ich das bei meinem 3D-Engine Teil. Die Grundidee war, eine 3D-Modell Klasse zu haben, mit der man Objekte laden und rendern kann. Nach Implementation diverser Features habe ich jetzt an die 30 Klassen, die alle irgendwie zusammenarbeiten. Das Problem dabei ist nur, dass man irgendwann alles auf derartig viele Objekte verteilt hat, dass das Zusammenspiel eben jener mehr Arbeit macht, als die eigentliche Logik. Flexibilität an Stellen wo man sie braucht, ist eine Last und kein Feature. Wenn du ein Problem hast, dass du entweder durch 5 Klassen in 10 Dateien (cpp/hpp) lösen kannst, oder aber durch einen 30 Zeilen Algorithmus, der zwar hässlich ist, aber geht, dann ist letzteres die bessere Lösung. Erst wenn du noch 3 mal ein ähnliches Problem hast, für dass du sie selben Klassen benutzen könntest, lohnen sich diese.
Ganz interessant ist dabei auch:
http://scientificninja.com/blog/write-games-not-engines