Wie kann ich in meinem Rollenspiel Objekte wie Java definieren?

21

Ich arbeite beiläufig an einem RPG-ähnlichen Spiel in Java, aber ich habe Schwierigkeiten herauszufinden, wie ich Objekte haben kann, die viele verschiedene Dinge können, ohne für jedes Objekt eine andere Klasse zu erstellen.

Wie würde ich zum Beispiel eine Axt erschaffen, die Bäume fällen und Monster angreifen könnte?

Wenn ich entweder die Hack- oder die Waffenklasse verlängere, kann ich die andere Klasse nicht verlängern.

Wenn ich Hacken und Waffe als Schnittstelle habe, werde ich viel duplizierten Code haben, wenn ein Dolch auch Monster angreifen kann und eine andere Axt Bäume fällen kann.

Ich hoffe, es gibt eine Möglichkeit, eine einzelne Item-Klasse zu haben und die Items und ihre jeweiligen Fähigkeiten aus einer Datei zu laden. Wenn das möglich ist, wie geht das? Wenn nicht, was ist dann der beste Weg, um Gegenstände in einem Spiel zu haben?

MESLewis
quelle

Antworten:

15

Die Antwort von Gregory Weir ist mein Favorit für die Strukturierung der Elementinstanzen, um mehrere Rollen auszuführen.

So laden Sie aus einer Datei:

Verwenden Sie zunächst YAML. YAML ist eine nützliche Datenbeschreibungssprache. Es kann relativ schnell analysiert, von Menschen gelesen und bearbeitet werden, unterstützt Binärdaten und es gibt Bibliotheken für die meisten Programmiersprachen, einschließlich Java. Hiermit wird die Frage gelöst, wie ich Daten aus Dateien in Objekte bekomme.

Zweitens verwenden Sie das Fliegengewicht Muster . Die meisten Daten, die Sie aus diesen Dateien lesen, sind statisch. Es ändert sich nicht pro Instanz ("Axt fügt 1W10 Grundschaden zu und bricht Holz, aber keinen Stein" - das gilt für alle fünf Achsen, die ein Spieler hat). Was Sie tatsächlich aus den YAML-Dateien lesen, sind diese platonischen Definitionen, und Ihre einzelnen Objektinstanzen haben nicht besessene (und konstante) Verweise darauf, zusammen mit instanzbezogenen Daten wie "Wie viele Schwünge, bevor ich breche?", "Hat der Spieler angegeben mir einen benutzerdefinierten Namen? "und so weiter.

Indem Sie die instanzübergreifenden Daten in einem einzelnen Objekt freigeben, sparen Sie viel Speicher und können Elemente ohne dauerhaften Spielstatus auf einfache Weise aktualisieren (Spiele oder Spielerdatenbank speichern).

Ihre Klassenstruktur sieht also ungefähr so ​​aus:

  • class Item - Eine Instanz pro Element
    • Besitzt eine Waffeninstanz
    • Besitzt eine Tool-Instanz
    • Hat einen benutzerdefinierten Namen usw.
  • Klassenwaffe - (Bis zu) eine Instanz pro Gegenstand
    • Ist eine ItemComponent
    • Bezieht sich auf WeaponDef
    • Has-a Bonus-Verzauberungsstufe usw.
  • class Tool - (Bis zu) eine Instanz pro Element
    • Ist eine ItemComponent
    • Bezieht sich auf ToolDef
    • Hat eine Haltbarkeit usw.
  • class WeaponDef - Eine Instanz pro Waffentyp
    • Aus einer Datei lesen, Felder sollten konstant sein.
    • Hat eine Grundschadensmenge, 1 oder 2 Hände usw.
  • class ToolDef - Eine Instanz pro Art von Werkzeug
    • Aus einer Datei lesen, Felder sollten konstant sein.
    • Hat eine Grundhaltbarkeit, Materialien, die es brechen kann, etc.
Marko Zajc
quelle
18

Das Entwurfsmuster Component (nicht Composite) eignet sich hervorragend für diesen Zweck: http://gameprogrammingpatterns.com/component.html

Grundsätzlich wäre eine Axe eine Instanz der Item-Klasse, die eine WeaponComponent und eine ToolComponent (möglicherweise) enthält. Um zu testen, ob etwas als Waffe verwendet werden kann, überprüfen Sie, ob eine WeaponComponent-Instanz daran angehängt ist, und sprechen Sie dann mit dieser WeaponComponent-Instanz, um die Waffeninformationen des Gegenstands abzurufen.

Das Laden aus einer Datei ist natürlich eine separate Übung.

Gregory Avery-Weir
quelle
Und natürlich können Sie, sobald Sie über Komponenten verfügen, die Schnittstellen wieder gut nutzen. Ihr Axe-Typ kann IChopper und IWeapon implementieren, dann aber das Verhalten der Komponente offenlegen, sodass Sie den Typ und die Implementierung nach Bedarf wiederverwenden und den Test für Komponenten ausschneiden können. Wenn alle Achsen die gleichen Fähigkeiten haben, aber unterschiedliche Statistiken, dann sind Sie goldrichtig. Wenn Sie Objekte mit einzigartigen Fähigkeiten benötigen, müssen Sie möglicherweise eine Spielkomponenten-Sammlung implementieren und Ihre Aktualisierungsroutinen die Objekte abfragen, um herauszufinden, was sie über welche Komponenten tun können.
CodexArcanum
6
@CodexArcanum: "Ihr Axe-Typ kann IChopper und IWeapon implementieren, kann dann aber das Verhalten der Komponente dafür offenlegen" - Was ist der Sinn davon? Es bläht nur Ihre Klassenhierarchie auf. Der Punkt des Komponentenmusters ist, dass Sie keine Axe-Klasse oder IChopper-Schnittstelle oder IWeapon-Schnittstelle benötigen, sondern nur konkrete Chopper- und Weapon-Komponenten und ein Element der obersten Ebene.
Ich arbeite derzeit an einem Komponentensystem für meine Spielgegenstände und habe wirklich nur eine große Beschwerde darüber, wie das Muster verwendet wird. In Anbetracht der Komponenten Waffe, Bekleidung und Verbrauchsmaterial kann ein Gegenstand theoretisch in Bezug auf Gegenstände "verfälscht" werden, die nicht gleichzeitig Waffen und Bekleidung sein können, oder in Bezug auf ein Kleidungsstück, das auch Verbrauchsmaterial ist. Logischerweise kann ein Artikel nur eine "Hauptkomponente" sein, aber wenn Sie die Komponenten einschränken, wird die Notwendigkeit eines Komponentensystems insgesamt zunichte gemacht. So ist einer der grundlegenden Mängel eines ansonsten erstaunlichen Systems
Krythic