Irgendwann MUSS sich eine Engine spezialisieren und etwas über das Spiel wissen. Ich werde hier auf einen Tangens gehen.
Nehmen Sie Ressourcen in einem RTS. Ein Spiel kann haben Credits
und ein Crystal
anderes Metal
undPotatoes
Sie sollten die OO-Konzepte richtig anwenden und max. Code-Wiederverwendung. Es ist klar, dass hier ein Konzept von Resource
existiert.
Daher entscheiden wir, dass Ressourcen Folgendes haben:
- Ein Haken in der Hauptschleife, um sich selbst zu erhöhen / zu verringern
- Eine Möglichkeit, den aktuellen Betrag abzurufen (gibt ein zurück
int
)
- Eine Möglichkeit, willkürlich zu subtrahieren / hinzuzufügen (Spieler, die Ressourcen übertragen, Einkäufe tätigen ...)
Beachten Sie, dass diese Vorstellung von a Resource
Abschüsse oder Punkte in einem Spiel darstellen könnte! Es ist nicht sehr mächtig.
Denken wir jetzt über ein Spiel nach. Wir können eine Art Währung haben, indem wir mit Pennies handeln und der Ausgabe einen Dezimalpunkt hinzufügen. Was wir nicht können, sind "augenblickliche" Ressourcen. Wie sagen "Stromnetzerzeugung"
Nehmen wir an, Sie fügen eine InstantResource
Klasse mit ähnlichen Methoden hinzu. Sie verschmutzen nun Ihren Motor mit Ressourcen.
Das Problem
Nehmen wir noch einmal das RTS-Beispiel. Angenommen, der Spieler spendet etwas Crystal
an einen anderen Spieler. Sie möchten etwas tun wie:
if(transfer.target == engine.getPlayerId()) {
engine.hud.addIncoming("You got "+transfer.quantity+" of "+
engine.resourceDictionary.getNameOf(transfer.resourceId)+
" from "+engine.getPlayer(transfer.source).name);
}
engine.getPlayer(transfer.target).getResourceById(transfer.resourceId).add(transfer.quantity)
engine.getPlayer(transfer.source).getResourceById(transfer.resourceId).add(-transfer.quantity)
Dies ist jedoch wirklich ziemlich chaotisch. Es ist allgemeiner Zweck, aber chaotisch. Schon resourceDictionary
jetzt, obwohl es ein vorschreibt, was bedeutet, dass Ihre Ressourcen Namen haben müssen! UND es ist pro Spieler, so dass Sie keine Teamressourcen mehr haben können.
Dies ist "zu viel" Abstraktion (ich gebe zu, kein brillantes Beispiel). Stattdessen solltest du einen Punkt erreichen, an dem du akzeptierst, dass dein Spiel Spieler und Kristall hat, dann kannst du nur (zum Beispiel)
engine.getPlayer(transfer.target).crystal().receiveDonation(transfer)
engine.getPlayer(transfer.source).crystal().sendDonation(transfer)
Mit einer Klasse Player
und einer Klasse, CurrentPlayer
in der CurrentPlayer
das crystal
Objekt automatisch das Material auf dem HUD für die Übertragung / das Senden von Spenden anzeigt.
Dies verschmutzt den Motor mit Kristall, dem Spenden von Kristall, den Nachrichten auf dem HUD für aktuelle Spieler und so weiter. Es ist sowohl schneller als auch einfacher zu lesen / schreiben / warten (was wichtiger ist, da es nicht wesentlich schneller ist)
Schlussbemerkungen
Der Ressourcenfall ist nicht brillant. Ich hoffe, dass Sie den Punkt dennoch sehen können. Wenn überhaupt, dann habe ich gezeigt, dass "Ressourcen gehören nicht in die Engine" , was ein bestimmtes Spiel benötigt und was für alle Begriffe von Ressourcen gilt, SEHR unterschiedliche Dinge sind. Was Sie normalerweise finden, sind 3 (oder 4) "Schichten"
- Der "Kern" - das ist die Lehrbuchdefinition der Engine, es ist ein Szenendiagramm mit Ereignis-Hooks, es handelt sich um Shader und Netzwerkpakete und eine abstrakte Vorstellung von Spielern
- Der "GameCore" - Dies ist ziemlich allgemein für die Art des Spiels, aber nicht für alle Spiele - zum Beispiel Ressourcen in RTS oder Munition in FPS. Die Spielelogik beginnt hier einzusickern. Hier würde sich unsere frühere Vorstellung von Ressourcen befinden. Wir haben diese Dinge hinzugefügt, die für die meisten RTS-Ressourcen sinnvoll sind.
- "GameLogic" ist SEHR spezifisch für das aktuelle Spiel. Sie finden Variablen mit Namen wie
creature
oder ship
oder squad
. Mit Vererbung Sie Klassen erhalten , die alle drei Schichten erstrecken (zum Beispiel Crystal
eine Resource
, die eine ist GameLoopEventListener
sagen wir)
- "Assets" sind für jedes andere Spiel nutzlos. Nehmen wir zum Beispiel die kombinierten KI-Skripte in Half Life 2, sie werden nicht in einem RTS mit derselben Engine verwendet.
Aus einer alten Engine ein neues Spiel machen
Dies ist sehr häufig. Phase 1 besteht darin, die Schichten 3 und 4 herauszureißen (und 2, wenn es sich um ein völlig anderes Spiel handelt). Nehmen wir an, wir machen ein RTS aus einem alten RTS. Wir haben immer noch Ressourcen, nur keinen Kristall und so weiter. Die Basisklassen in den Schichten 2 und 1 sind also immer noch sinnvoll. Alles, worauf in 3 und 4 verwiesen wird, kann verworfen werden. So machen wir es. Wir können es jedoch als Referenz für das überprüfen, was wir tun möchten.
Verschmutzung in Schicht 1
Das kann passieren. Abstraktion und Leistung sind Feinde. UE4 bietet zum Beispiel eine Menge optimierter Fälle von Komposition (wenn Sie also möchten, dass X und Y schnell zusammenarbeiten - es weiß, dass es beides tut) und ist daher WIRKLICH ziemlich groß. Das ist nicht schlecht, aber zeitaufwändig. Layer 1 entscheidet, wie "Sie Daten an Shader übergeben" und wie Sie Dinge animieren. Es ist IMMER gut, das Beste für Ihr Projekt zu tun. Versuchen Sie einfach, für die Zukunft zu planen. Die Wiederverwendung von Code ist Ihr Freund. Erben Sie, wo es Sinn macht.
Ebenen klassifizieren
LETZT (ich verspreche es) hab keine Angst vor Schichten. Engine ist ein archaischer Begriff aus den alten Zeiten der Pipelines mit fester Funktion, in denen Engines ähnlich grafisch arbeiteten (und als Ergebnis hatten sie viele Gemeinsamkeiten). Die programmierbare Pipeline stellte dies auf den Kopf und als solche wurde "Layer 1" verschmutzt mit welchen effekten die entwickler erreichen wollten. KI war das Unterscheidungsmerkmal (wegen der Vielzahl von Ansätzen) von Motoren, jetzt ist es KI und Grafik.
Ihr Code sollte nicht in diesen Ebenen abgelegt werden. Sogar die berühmte Unreal-Engine hat VIELE verschiedene Versionen, die jeweils für ein anderes Spiel spezifisch sind. Es gibt nur wenige Dateien (außer vielleicht ähnlichen Datenstrukturen), die unverändert geblieben wären. Das ist okay! Wenn Sie ein neues Spiel aus einem anderen machen möchten, dauert es länger als 30 Minuten. Der Schlüssel ist zu planen, zu wissen, welche Teile zu kopieren und einzufügen sind und was zurückzulassen ist.