Also mache ich ein Spiel, in dem du Schiffe an Orte schicken kannst, an denen du Rohstoffe wie Holz, Eisen, Gold usw. verkaufen oder kaufen kannst.
Jetzt habe ich mich gefragt, wie die Ressourcen im Spiel erstellt werden sollen. Ich habe mir 2 Optionen ausgedacht
Erstellen Sie eine Klasse für jede Ressource:
public class ResourceBase { private int value; // other base properties } public class Gold : ResourceBase { public Gold { this.value = 40 // or whatever } }
Erstellen Sie Instanzen einer Ressourcenklasse
public class Resource { string name; int value; public Resource(string name, int value) { this.name = name; this.value = value; } } // later on... Resource gold = new Resource("Gold",40);
Mit der zweiten Option ist es möglich, die Spielressourcen aus einer resources.json-Datei zu füllen. Diese Struktur gefällt mir irgendwie.
Neue Ideen / Designmuster / Strukturen sind immer willkommen!
EDIT: Es ist ein bisschen wie Assassins Creed Black Flag Companion App. Siehe die Ressourcenleiste auf dem Bild unten
BEARBEITEN 2: Ich habe einige Nachforschungen zum "Laden von Elementen / Ressourcen aus JSON-Datei" angestellt und dieses Blog gefunden: Power of JSON in Game Development - Items . Es zeigt das Beste aus Option 1 und Option 2. Sie können weiterhin jeder Ressource Funktionen hinzufügen :)
quelle
enum
stattdessen eine.Antworten:
Entscheiden Sie sich für den zweiten Ansatz, da Sie jederzeit neue Ressourcentypen oder -elemente einführen können, ohne den Code neu schreiben oder aktualisieren zu müssen ( datengesteuerte Entwicklung ).
Bearbeiten:
Um ein bisschen mehr darüber zu sagen, warum dies im Allgemeinen eine gute Praxis ist, auch wenn Sie zu 100% sicher sind, dass sich ein bestimmter Wert niemals ändern wird.
Nehmen wir das in den Kommentaren erwähnte Beispiel für ein Konsolenspiel, denn dies ist ein guter Grund, warum Sie nichts hart codieren sollten, es sei denn, Sie haben wirklich (oder möchten), z. B. Verschlüsselungsschlüssel, Ihren eigenen Namen usw.
Wenn Sie ein Spiel auf Konsolen veröffentlichen, müssen diese in der Regel einen Überprüfungsprozess durchlaufen, bei dem die QS des Konsolenherstellers das Spiel testet, es durchspielt, nach Problemen sucht usw. Dies ist obligatorisch und kostet Geld, viel Geld. Ich habe mal gelesen, dass eine Veröffentlichung allein für die Zertifizierung 30.000-50.000 US-Dollar kosten könnte.
Stellen Sie sich vor, Sie wollen Ihr Spiel veröffentlichen, zahlen die 30.000 US-Dollar und warten. Und plötzlich merkst du, dass einige deiner Spielwerte buchstäblich gebrochen sind. Nehmen wir an, Sie können Eisenbarren für 50 Gold kaufen und für 55 Gold verkaufen.
Wie geht's? Wenn Sie dieses Zeug fest programmiert haben, müssen Sie eine neue Update- / Release-Version erstellen, die noch einmal überprüft werden muss, sodass Sie im schlimmsten Fall erneut für die Neuzertifizierung zahlen müssen! Ich wette, Ubisoft hat nichts dagegen, aber für Ihre eigene kleine Indie-Spiele-Entwicklertasche ... autsch!
Stellen Sie sich jedoch vor, das Spiel sucht nur gelegentlich nach aktualisierten Spieldefinitionen (z. B. in Form einer JSON-Datei). Ihr Spiel kann jederzeit die neueste Version herunterladen und verwenden, ohne dass ein neues Update erforderlich ist. Sie können dieses Ungleichgewicht / Exploit / Bug jederzeit beheben, ohne eine erneute Zertifizierung oder ein anderes bezahltes Geld zu benötigen. Nur eine kleine Designentscheidung, die Sie nicht für lohnenswert hielten. Sie haben nur fünfstellige Beträge gespart! Ist das nicht großartig? :)
Versteh mich einfach nicht falsch. Dies gilt auch für andere Arten von Software und Plattformen. Das Herunterladen aktualisierter Datendateien ist für den Standardbenutzer im Allgemeinen viel einfacher und praktischer, unabhängig davon, ob es sich um ein Spiel oder eine Anwendung oder ein Tool handelt. Stellen Sie sich ein Spiel vor, das unter Programme in Windows installiert ist. Ihr Updater benötigt Administratorrechte, um Änderungen vorzunehmen, und Sie können laufende Programme nicht ändern. Mit DDD lädt Ihr Programm einfach die Daten herunter und verwendet sie. Der Player bemerkt möglicherweise nicht einmal, dass ein Update durchgeführt wurde.
quelle
Als Faustregel gilt, dass Sie unterschiedliche Klassen verwenden, wenn Objekte unterschiedlichen Code und Instanzen derselben Klasse erfordern, wenn die Objekte nur unterschiedliche Werte erfordern.
Wenn die Ressourcen unterschiedliche Spielmechanismen haben, die für sie einzigartig sind, kann es sinnvoll sein, sie mit Klassen darzustellen. Zum Beispiel, wenn Sie Plutonium haben , die eine Halbwertszeit und Kaninchen hat , die gemäß der fortzupflanzen Fibonacci - Sequenz , dann könnte es Sinn machen , eine Basis-Klasse zu haben ,
Resource
mit einem VerfahrenUpdate
als no-op und zwei abgeleiteten Klassen implementiertHalfLifeResource
undSelfGrowingResource
die Überschreiben Sie diese Methode, um den Wert zu verringern / erhöhen (und fügen Sie möglicherweise auch Logik ein, um zu steuern, was passiert, wenn Sie beide nebeneinander speichern).Aber wenn Ihre Ressourcen wirklich nur dumme Zahlen sind, macht es keinen Sinn, sie mit etwas Besonderem als einer einfachen Variablen zu implementieren.
quelle
Ich möchte hinzufügen, dass es zwei zusätzliche Optionen gibt:
Schnittstelle: Sie können es in Betracht ziehen, wenn die Ressourcenklasse nur ein "Speicher" für 5 Ganzzahlen wäre und jede andere Entität eine andere Logik in Bezug auf Ressourcen hätte (z. B. Spielerausgaben / Beute, Stadtproduktionen) Ressource). In diesem Fall möchten Sie möglicherweise überhaupt keine Klasse - Sie möchten lediglich offenlegen, dass einige Entitäten über eine Variable verfügen, mit der andere interagieren können:
Darüber hinaus hat dies den Vorteil, dass Sie eine Stadt mit genau demselben Code plündern können, wie Sie eine feindliche Flotte plündern würden, wodurch die Wiederverwendung von Codes gefördert wird.
Der Nachteil ist, dass das Implementieren einer solchen Schnittstelle sich als mühsam erweisen kann, wenn viele Klassen sie implementieren. Daher können Sie möglicherweise Schnittstellen verwenden, jedoch nicht für das ursprüngliche Problem, indem Sie sie mit Option 1 oder 2 lösen:
Instanzen (mit Aufzählung): In einigen Fällen wäre es wünschenswert, bei der Definition des Ressourcentyps Aufzählung anstelle von Zeichenfolge zu verwenden:
Dies bietet ein wenig "Sicherheit", da Sie in Ihrer IDE eine Liste aller gültigen Ressourcen erhalten, wenn Sie sie nach dem Schreiben des Punkts
ResourceType = Resource.
zuweisen. Außerdem gibt es weitere "Tricks" mit Aufzählungen, die Sie möglicherweise benötigen, z. B. den expliziten Typ oder die Komposition / Flags was ich mir beim basteln als nützlich vorstellen kann:Was das Beste ist - es gibt keine Silberkugel, aber ich persönlich würde mich zu jeder Form von Instanzen neigen, sie sind vielleicht nicht so schick wie eine Benutzeroberfläche, aber sie sind einfach, überladen keinen Erbschaftsbaum und sind weithin bekannt.
quelle
my-great-enum
) zu einer C # -Darstellung von enum (MyGreatEnum
) vorzunehmen .Sie sollten Option 1 verwenden, die drei Vorteile bietet:
new Gold(50)
resource instanceof Gold
quelle
Wenn Ihre Ressourcen keine eigene Geschäftslogik haben oder spezielle Szenarien für die Interaktion mit der Umgebung, andere Ressourcen (außer dem von Ihnen abgedeckten Handel) oder der Player, können Sie mit Option zwei ganz einfach neue hinzufügen.
Wenn Sie sich überlegen müssen, was passieren würde, wenn Sie zwei Rohstoffe zum Herstellen mischen, wenn die Rohstoffe sehr unterschiedliche Eigenschaften haben können (ein Eimer Wasser unterscheidet sich stark von einem Klumpen Kohle) oder andere komplexe wirtschaftliche Wechselwirkungen, dann ist Ansatz 1 weitaus flexibler für den Motor, aber nicht die Daten.
quelle