Codierung ist eigentlich nicht so schwer . Der schwierige Teil besteht darin, Code zu schreiben, der Sinn macht, lesbar und verständlich ist. Ich möchte also einen besseren Entwickler finden und eine solide Architektur erstellen.
Also möchte ich eine Architektur für NPCs in einem Videospiel erstellen . Es ist ein Echtzeit-Strategiespiel wie Starcraft, Age of Empires, Command & Conquers usw. usw. Also werde ich verschiedene Arten von NPCs haben. Ein NPC kann viele Fähigkeiten (Methoden) von ihnen haben ein zu: Build()
, Farm()
und Attack()
.
Beispiele:
Arbeiter können Build()
und Farm()
Krieger können Attack()
Citizen kann Build()
, Farm()
und Attack()
Fischer können Farm()
undAttack()
Ich hoffe alles ist soweit klar.
Jetzt habe ich meine NPC-Typen und ihre Fähigkeiten. Kommen wir aber zum technischen / programmatischen Aspekt.
Was wäre eine gute programmatische Architektur für meine verschiedenen Arten von NPCs?
Okay, ich könnte eine Basisklasse haben. Eigentlich denke ich, dass dies ein guter Weg ist, um am DRY- Prinzip festzuhalten . So kann ich Methoden wie WalkTo(x,y)
in meiner Basisklasse haben, da jeder NPC sich bewegen kann. Aber jetzt kommen wir zum eigentlichen Problem. Wo setze ich meine Fähigkeiten um? (Denken Sie daran : Build()
, Farm()
und Attack()
)
Da die Fähigkeiten aus der gleichen Logik bestehen, wäre es ärgerlich / DRY-Prinzip zu brechen, sie für jeden NPC (Arbeiter, Krieger, ..) zu implementieren.
Okay, ich könnte die Fähigkeiten innerhalb der Basisklasse implementieren. Dies würde eine Art von Logik erfordern , dass überprüft , wenn ein NPC Fähigkeit X verwenden kann IsBuilder
, CanBuild
.. Ich denke , es ist klar , was ich ausdrücken will.
Aber ich fühle mich mit dieser Idee nicht sehr wohl. Das klingt nach einer aufgeblähten Basisklasse mit zu viel Funktionalität.
Ich benutze C # als Programmiersprache. Mehrfachvererbung ist hier also keine Option. Mittel: Zusätzliche Basisklassen wie Fisherman : Farmer, Attacker
funktionieren nicht.
quelle
Antworten:
Zusammensetzung und Schnittstellenvererbung sind die üblichen Alternativen zur klassischen Mehrfachvererbung.
Alles, was Sie oben beschrieben haben und mit dem Wort "can" beginnen, kann mit einer Schnittstelle wie in
ICanBuild
oder dargestellt werdenICanFarm
. Sie können so viele dieser Schnittstellen erben, wie Sie für erforderlich halten.Sie können "generische" Gebäude- und Landwirtschaftsobjekte über den Konstruktor Ihrer Klasse übergeben. Hier kommt die Komposition ins Spiel.
quelle
ICanBuild
. Dass Sie auch Tools zum Erstellen haben, ist in der Objekthierarchie von untergeordneter Bedeutung.Wie bereits auf anderen Postern erwähnt, könnte eine Komponentenarchitektur die Lösung für dieses Problem sein.
In diesem Fall erweitern Sie die Aktualisierungsfunktion, um alle Funktionen zu implementieren, die der NPC haben sollte.
Durch Iterieren eines Komponentencontainers und Aktualisieren jeder Komponente kann die spezifische Funktionalität jeder Komponente angewendet werden.
Da jeder Objekttyp gewünscht wird, können Sie eine Form des Factory-Musters verwenden, um die einzelnen gewünschten Typen zu erstellen.
Ich bin immer auf Probleme gestoßen, da die Komponenten immer komplexer werden. Wenn Sie die Komplexität der Komponenten niedrig halten (eine Verantwortung), können Sie dieses Problem beheben.
quelle
Wenn Sie Schnittstellen wie diese definieren, muss
ICanBuild
Ihr Spielsystem jeden NPC nach Typ untersuchen, was in OOP normalerweise verpönt ist. Zum Beispiel :if (npc is ICanBuild)
.Du bist besser dran mit:
Dann:
... oder Sie können natürlich eine Reihe verschiedener Architekturen verwenden, z. B. eine domänenspezifische Sprache in Form einer fließenden Schnittstelle zum Definieren verschiedener Arten von NPCs usw., in der Sie NPC-Typen erstellen, indem Sie verschiedene Verhaltensweisen kombinieren:
Der NPC-Builder könnte einen implementieren
DefaultWalkBehavior
, der im Fall eines fliegenden NPC, der aber nicht laufen kann, überschrieben werden kann.quelle
if(npc is ICanBuild)
undif(npc.CanBuild)
. Auch wenn ich dennpc.CanBuild
Weg von meiner jetzigen Einstellung vorziehen würde .Ich würde alle Fähigkeiten in separate Klassen einteilen, die von Fähigkeit erben. Dann haben Sie in der Einheitentypklasse eine Liste von Fähigkeiten und anderen Dingen wie Angriff, Verteidigung, maximale Gesundheit usw. Haben Sie auch eine Einheitenklasse, die die aktuelle Gesundheit, den aktuellen Standort usw. hat und den Einheitentyp als Mitgliedsvariable hat.
Definieren Sie alle Einheitentypen in einer Konfigurationsdatei oder einer Datenbank, anstatt sie fest zu codieren.
Dann kann der Level-Designer die Fähigkeiten und Statistiken der Einheitentypen leicht anpassen, ohne das Spiel neu zu kompilieren, und die Leute können Mods für das Spiel schreiben.
quelle