Welche Codephilosophie / Struktur der Abstraktion / Programmgestaltung würde es ermöglichen, ein Spiel sowohl mit 2D- als auch mit 3D-Grafiken (separat) zu verwenden, ohne die Spielelogik neu codieren zu müssen?
Wir sprechen davon, denselben Code zu verwenden, ein Minimum an Dingen zu ändern (z. B. Dateinamen für 2D-Assets gegen Dateinamen für 3D-Assets auszutauschen) und möglicherweise einige Spezialisierungen einer Basisklasse pro Generika / Vorlagen einzufügen.
Um es in einen realen Kontext zu stellen, in dem es Sinn macht: Stellen Sie sich ein LAN-Multiplayer-Spiel vor, in dem es einen erstklassigen, leistungshungrigen 3D-Client für die Spieler mit einigen wirklich guten Gamer-Rigs und einen bescheideneren 2D-Client für die alten gibt staubige Kisten, die jemand auf seinem Dachboden gefunden hat. Aber es ist immer noch dasselbe Spiel - dieselben Ereignisse werden registriert (jemand hat eine Münze abgeholt), dasselbe Netzwerkprotokoll wird verwendet, die Welten sind proportional usw.
Um es in einen MVC-Kontext zu stellen: Die Controller sind exakt gleich (durch Drücken der Taste "Auf" wird die Beschleunigung des Spielers auf 3,5 Einheiten / Sekunde eingestellt), die Ansichten sind völlig unterschiedlich (2D gegenüber 3D) und das Modell ist das gleiche mit Ausnahme von allem, was in direktem Zusammenhang mit Grafiken steht (alle 5 Sekunden wird eine Kollisionsprüfung für die Umgebung durchgeführt, und es wird derselbe Algorithmus verwendet. Beachten Sie, dass dies bedeuten würde, dass für alle Spielobjekte in der 2D-Version eine Z-Koordinate vorhanden ist, dies ist jedoch der Fall nur ignoriert oder dem Benutzer auf andere Weise angezeigt werden, z. B. durch einen Schatten, der weiter links angezeigt wird, wenn sich der Spieler in der Luft befindet).
Was dieses Thema so faszinierend macht, ist, dass es den Entwickler zwingen würde, eine sehr klare Vorstellung davon zu haben, wie seine Daten strukturiert sind und wie die Kontrolle fließt. Beachten Sie, dass dies nichts anderes als die Verwendung einer Grafikbibliothek wie SDL, D3DX oder OpenGL bedeutet. Keine Spiel-Engines!
Da dies eine größtenteils theoretische Frage ist, werde ich Programmiersprachen weglassen, aber wenn Sie ein Beispiel geben möchten, können Sie jede Sprache verwenden, die Sie mögen, C ++, wenn Sie das ganze Schwein gehen wollen, oder sogar Brainfuck, wenn Sie das Gefühl haben bis zur Herausforderung (Konkrete Antworten werden ebenso geschätzt wie abstrakte!).
quelle
Antworten:
Ich denke, alles, was Sie brauchen würden, wäre eine Abstraktionsebene, die Ihre Grafikbibliothek umhüllt. Sie würden für jede Bibliothek, die Sie verwenden würden, eine neue benötigen, und jede müsste genau dieselbe externe API haben.
Denken Sie an die Lokalisierung von Zeichenfolgen: Anstatt die Zeichenfolge "Inventar" in Ihrem Spiel fest zu codieren, rufen Sie stattdessen Ihre (möglicherweise benutzerdefinierte) Lokalisierungsbibliothek auf, die je nach Kontext einige Prozesse ausführt und eine geeignete Zeichenfolge zurückgibt das Spiel.
Auf die gleiche Weise würden alle Aufrufe Ihrer Grafik-Engine über Ihren Wrapper erfolgen.
Auf diese Weise begrenzen Sie, welche Befehle Sie Ihrer Grafik-Engine geben können. Hier sind einige wesentliche:
Und einige andere, die Sie bei der Arbeit an Ihrem Projekt finden.
Wenn Sie eine strikt typisierte objektorientierte Sprache verwenden, würden Sie die obigen Befehle als Schnittstelle bezeichnen , die alle Ihre Wrapper implementieren. Vorzugsweise sind dies die einzigen nicht geschützten / öffentlichen Methoden.
Erstellen Sie jetzt einen neuen Wrapper für jede Ihrer Grafikbibliotheken und implementieren Sie die API . Wenn Sie den Befehl zum Zeichnen von __ bei __ erhalten, müssen Sie das Sprite oder Modell mithilfe von Code erstellen und in Ihre Umgebung zeichnen. Dies kann einige Tricks erfordern, z. B. das Speichern jedes Sprites in einem Hash, um zu einem anderen Zeitpunkt durch ein bestimmtes Symbol wieder zugänglich zu sein.
Beim Erstellen von Karten wäre es am effizientesten, jede Karte für jede Grafik-Engine vorab zu erstellen und eine Suche durchzuführen. Alternativ können Sie die Karte in Ihrer eigenen benutzerdefinierten Datenstruktur speichern und dann mit Ihrem Wrapper eine Karte aus dieser Datenstruktur erstellen.
Hoffe das hilft dir den Einstieg =]
quelle
Das Erstellen der Architektur Ihres Spiels mit einem Paradigma, das MVC nahe genug kommt, um eine vollständige Abstraktion des Anzeigecodes zu ermöglichen, wäre für jedes große Projekt wahrscheinlich recht schwierig. Es scheint jedoch das größte Hindernis für die Erstellung eines Spiels zu sein, das sowohl einen 2D- als auch einen 3D-Client unterstützt, ein Spiel zu entwerfen, in dem beide Clients gleichermaßen fähig sind.
Es wäre notwendig, das Design Ihres Spiels mit der vollen Absicht zu beginnen, die beiden Clients zu erstellen und zu unterstützen, und es wäre wahrscheinlich am sichersten, alle Spielfunktionen auf das zu beschränken, was für den 2D-Client sinnvoll ist.
Wenn Sie beispielsweise keine eingeschränkte Funktionalität festlegen, können Sie Ebenen erstellen, in denen wichtige Informationen oder Objekte nur aus bestimmten Blickwinkeln sichtbar sind. Während dies für 3D-Clients mit einer Betrachtungsfreiheit von 360 Grad in Ordnung wäre, wenn Ihr 2D-Client nicht explizit einen Betrachtungswinkel unterstützt, der für jedes dieser wichtigen Objekte sichtbar ist, würden Sie die Benutzer des Clients beeinträchtigen.
Es ist am besten, eine bestimmte Anzahl von Betrachtungswinkeln für den 2D-Client festzulegen (8 oder 16 oder so) und den gesamten Inhalt so zu entwickeln, dass er diesen Einschränkungen entspricht. Wenn Sie Ebenen und Objekte haben, die nur aus bestimmten Winkeln angezeigt werden können, kann dies in einem 3D-Client leider recht seltsam aussehen.
Meiner Meinung nach wäre es eine schlechte Wahl, ein Spieldesign zu versuchen, das 2D- und 3D-Clients ermöglicht, die die gleichen Fähigkeiten haben sollen. Ich denke, es wäre eine bessere Nutzung der Ressourcen, um asymmetrische Spieloptionen zu entwerfen und jedem Kunden zu ermöglichen, seine Stärken auszunutzen. Zum Beispiel, wenn der 2D-Client in erster Linie auf eine strategische Perspektive auf die Spielwelt ausgerichtet war und der 3D-Client für das taktische Gameplay verwendet wurde.
quelle
Ich denke, Sie haben Ihre eigene Frage so ziemlich beantwortet:
Wenn Sie also eine angemessene Abstraktion zwischen Eingabe, Spielelogik usw. und Grafiken bereitstellen, haben Sie das Problem gelöst.
Dies ist im Wesentlichen der Punkt des MVC-Modells, insbesondere in Bezug auf Desktop- und Webanwendungen: Es können mehrere Clients auf dieselben Daten zugreifen und diese bearbeiten (z. B. eine Weboberfläche, ein mobiler Client und ein Desktop-Client für E-Mails).
quelle
Halten Sie es einfach, wenn Sie es einfach wollen: - Schreiben Sie die Spiellogik, um die Objekte zu bewegen. Speichern Sie keine Daten, die sich auf das Rendern beziehen. - Schreiben Sie Renderer, die die Möglichkeit haben, den Status der Spieldaten anzuzeigen und zu zeichnen.
Hierfür können Sie mehr oder weniger komplizierte Programmiertechniken verwenden. Das einzige, was Sie brauchen, ist eine Möglichkeit, zu "zusätzlichen" Daten zu gelangen, die Sie für jedes Spielobjekt rendern müssen. Der einfachste Weg ist, keine zusätzlichen Daten zu benötigen! Wenn das Spielobjekt ein "Assistent" ist, zeichnen Sie einen Assistenten.
Wenn Sie kompliziertere Methoden benötigen, sollten Sie Polymorphismus, Erinnerungsmuster, Hash-Tabellen, void * -Zeiger usw. berücksichtigen. Überentwickeln Sie diese nicht (die meisten dieser Methoden sind überentwickelt).
quelle