Im Wesentlichen, was Aron_dc sagte, obwohl ich noch weiter gehen würde. Im Allgemeinen sollten Sie versuchen, Ihre Klassenstruktur so flach wie möglich zu halten und Code (Algorithmen) von Daten (Attributen) zu trennen.
Sie benötigen nur eine Waffenklasse für Nahkampf- / Sofortschlagwaffen. Diese Klasse kann entweder sofort überprüfen, was sie getroffen hat, oder sie erhält ein Objekt, dem sie Schaden zufügen kann. Dies schließt Fernkampfwaffen ein, die wie ein Laser sofort getroffen werden (eine Waffe könnte es auch sein, wenn Sie sie nicht zu realistisch modellieren möchten).
class InstantWeapon{
Sprite sprite; //should be inherited from EquippableObject, or DrawableGameObject, or something
WeaponType weaponType;
DamageType dmgType;
Double dmgOnHit;
...
void Hit(ObjectWithHitPoints o){...}
void Hit(Ray hitRay)
}
Eine zweite Klasse wird für Partikellaichwaffen verwendet, beispielsweise für einen Feuerballstab. Diese Waffen beschädigen nicht direkt, sondern erzeugen ein neues Objekt, das sich nach seiner eigenen Logik bewegt und Schaden verursacht, wenn es mit einem Objekt kollidiert. In diesem Fall enthält das Partikel alle erforderlichen Informationen (Schadensmenge und -typ, Radius usw.) und es ist einfach, ihnen eine benutzerdefinierte Logik zu geben (Zielsuchrakete oder Verlust von Schaden, je länger es sich bewegt, ...).
class ParticleSpawner{
InteractiveParticle sampleParticle;
void Fire(Vector3 position, Vector3 direction){
ParticleEngine.Add(sampleParticle.Clone());
}
}
Je nachdem, wie komplex Ihre Waffe und Ihr Schadenssystem sein sollen, können Sie sich das Komponentenmuster ansehen . Das Grundprinzip ist, dass Sie eine Weapon
Klasse und eine Liste mit mehreren Instanzen der DamageComponent
Klasse haben würden. Die DamageComponent
Klasse enthält den Algorithmus und die Daten für alle Waffeneffekte, die für diese eine Waffe gelten.
class Weapon{
List<DamageComponent> damageComponents;
void Fire(Ray hitRay){
foreach(component : DamageComponent)
component.Apply(hitRay);
}
}
Jede Komponente kann jetzt einen Feuerball erzeugen, feindliche Rüstungen reduzieren, Standardschaden verursachen, einen "Feuer" -Effekt auf Ziele anwenden usw. Zusätzlich kann jede Komponente den Waffenschwung so handhaben, wie sie will. Holen Sie sich nur das Ziel direkt vor oder spalten Sie in einem weiten Bogen, etc ...
Beachten Sie auch, dass das Komponentensystem an anderen Stellen nützlich sein kann.
- Verschiedene Arten von Rüstungskomponenten schützen unterschiedlich vor verschiedenen Schadensarten
- Partikel auf Update-Komponenten können ein einzelnes Partikel auf unterschiedliche Weise beeinflussen
- Fähigkeiten, die durch Fertigkeiten oder Objekte gewährt werden, müssen nur einmal implementiert werden, da sie dem Spieler einfach die Can-Fly- oder die Can-See-Underground-Komponente hinzufügen.
Im Allgemeinen können Sie viele kleine Komponenten erstellen, die für sich genommen nicht viel bewirken, aber äußerst komplexe Systeme bilden können, da ihre Kombinationen mit jeder neuen Implementierung exponentiell zunehmen.
Die daraus resultierenden Effekte des Systems können sehr komplex werden, was sehr schön ist, wenn Sie ein aufstrebendes Verhalten wünschen und Dinge auf komplexe Weise modellieren möchten. Dies macht es jedoch schwieriger, Dinge wie Waffenbalance oder feindliche Schwierigkeiten zu tun. Ein beliebtes Beispiel ist Diablo3 mit seinen zufälligen Fähigkeitskomponenten. Bestimmte Kombinationen sind viel stärker als die anderen.
Nachteile der ersten (Unterklasse):
Nachteile des zweiten (Strategiemuster):
Vorteile des zweiten (Strategiemuster):
Wenn sich Ihre Waffen nur in einigen Statistiken unterscheiden, müssen Sie nichts davon verwenden. Fügen Sie die Statistiken einfach in die Basisklasse ein und füllen Sie sie entsprechend Ihren Wünschen aus (boolesche Zweihandigkeit, int Schaden, Stringname, ....).
quelle
Wenn Sie nur Parameter ändern, ist keine Vererbung erforderlich. Wenn Sie jedoch andere Funktionen hinzufügen möchten, empfehlen wir Ihnen, Unterklassen zu verwenden. Ich bezweifle, dass Sie in einem Konsolenspiel zusätzliche Funktionen haben, nur Parameter wie
damage
undaddsAttributes
.Dies ist jedoch sehr spezifisch für die Implementierung.
quelle
Ich neige dazu, die Vererbung so weit wie möglich zu vermeiden, wenn es darum geht, Objekte anhand von Daten zu klassifizieren , die in Spielen verwendet werden , anstatt Systeme zu klassifizieren , die in Spielen verwendet werden. Was ich meine ist, es kann sinnvoll sein, eine
Animator
Klasse und dann eine zu habenSpriteAnimator
und die zuTileAnimator
erben,Animator
wenn die Verhaltensunterschiede in ihren Funktionen diskret fest codiert werden müssen. Wenn die Unterschiede im Verhalten von aSword
und anAxe
einfach durch die Werte in einer Gruppe von Statistiken bestimmt werden sollen, die am besten als Datencontainer für Spiele behandelt werden, sollten sie nur durch Parameter definiert werden, die alle Objekte gemeinsam haben.Wenn Sie mit dem MVC-Muster vertraut sind, entspricht die Verwendung der Mehrfachvererbung zum Erstellen ähnlicher Datencontainer dem Erstellen einer Reihe von Controllern, die sich nur in den Werten in den Datenelementen unterscheiden. Offensichtlich ist es besser, nur einen Controller zu haben und sich auf das Modell zu verlassen, um die benötigten Werte abzurufen.
Sie haben nicht eingehend untersucht, welche Eigenschaften Ihre Klassen haben, aber das Waffeninventar scheint viel mehr von einem datengesteuerten Design zu profitieren . Haben Sie also nur eine Waffenklasse und weisen Sie ihr verschiedene Eigenschaften zu. Um sie zu benennen, ist der Name einfach ein schreibgeschütztes Zeichenfolgenmitglied.
Wenn Sie hybride Gegenstände haben möchten (wie oben
SwordWithCannon
erwähnt), definieren Sie möglicherweise eine Waffenklasse, die Eigenschaften mehrerer Waffenobjekte annehmen kann, d. H. in einem Vektor oder einer Liste, die einen oder mehrere Sätze von Eigenschaften enthält.quelle