Ich habe ein RPG-Spiel mit mehreren Story-Threads entworfen. Je nach Wahl des Benutzers können einige Dinge passieren oder auch nicht. Sie können dasselbe auf verschiedene Weise erreichen. Das Ende kann unterschiedlich sein und so weiter.
Ich habe eine einfache Entscheidungs-Engine implementiert, die funktioniert, aber einen großen Fehler aufweist. Sobald Sie eine Entscheidung treffen, wird die Geschichte sofort von Ihrer Entscheidung beeinflusst. Das bedeutet, dass Sie keine Entscheidung treffen können, die Sie in ferner Zukunft betrifft . Dies liegt daran, dass sich die Story wie ein Zweig in einer Baumstruktur entfaltet und immer wissen muss, welcher Knoten der nächste ist. Unter der Haube werden die Entscheidungen mithilfe einer Warteschlange implementiert: Jeder Knoten kennt den vorherigen und den nächsten Knoten (oder wenn es sich um einen Entscheidungsknoten handelt, wartet er auf Benutzereingaben, um den nächsten Knoten festzulegen).
Ich habe viele Spiele mit komplexen Entscheidungsprozessen gesehen und ich frage mich, wie sie gemacht werden. Gibt es ein spezielles Design, das die Dinge wirklich einfach macht? Hat jemand etwas Ähnliches gemacht und kann mir einen Hinweis geben, wie ich das angehen kann?
UPDATE 1:
Ein wichtiger Aspekt ist es, den Story-Code irgendwie unabhängig zu halten, damit er aus einer externen Datei heraus bearbeitet werden kann. Ich plane, dies als Engine zu verwenden, sodass selbst die möglichen Auswahlen aus einer externen Datei stammen müssen. Der Code muss absolut abstrakt sein.
Außerdem interessiere ich mich für eine Designlösung, eine gute Möglichkeit, dies zu tun, wie andere es tun oder getan haben.
quelle
if (isTree)
eineisTree
globale Variable nicht prüfen oder beibehalten, da die Story diese Wahlmöglichkeit haben kann oder nicht. Weißt Du, was ich meine? Es ist eher eine auserlesene Engine, die mehrere Geschichten abdeckt.isTree=true
, tut er später noch etwas anderes, wie einen Schulkameraden zu bekämpfen, der im Gegenzug seinen Baum abhackt, während der Baum noch jung ist weil er seinen Arsch getreten hat. Jetzt haben wir 2 Variablen, die die Existenz des BaumesisTree==true' and
didFightBrat == false` beeinflussen. Weißt Du, was ich meine? Und die Kette kann für immer weitergehen, die Existenz des Baumes kann durch eine unbekannte Anzahl von Faktoren beeinflusst werden. Weißt Du, was ich meine?Antworten:
Sie können die Warteschlange auch in einen gerichteten azyklischen Graphen (DAG) verallgemeinern. Sie können darüber auf Wikipedia lesen. Grundsätzlich kann jeder Knoten einen oder mehrere übergeordnete Knoten haben, von denen er "abhängt". Zyklen sind nicht zulässig, dh wenn A von B abhängt, kann B nicht von A abhängen (direkt oder über eine indirekte Kette anderer Knoten).
Jeder Knoten befindet sich in einem "aktiven" oder "inaktiven" Zustand und darf nur dann aktiv werden, wenn alle übergeordneten Knoten bereits aktiv sind. Die Struktur des Graphen (welche Knoten sind vorhanden und wie sind sie verbunden) ist Teil der Spieldaten, aber der Aktiv / Inaktiv-Status ist Teil der Sicherungsdaten des Spielers.
Auf diese Weise können Sie Dinge modellieren wie: Wenn Sie einen Baum pflanzen, markieren Sie eine Aufgabe "plantedTree" als aktiv; Dann, später im Spiel, nennt eine andere Aufgabe "treeGrown" sowohl "plantedTree" als auch einen anderen Knoten (Teil der Geschichte) als seine Eltern. Dann wird "treeGrown" nur dann aktiv, wenn der Spieler zu diesem Punkt in der Geschichte gelangt und auch "plantedTree" aktiv ist.
Sie können andere Funktionen einschließen, z. B. Knoten, die aktiviert werden, wenn einer ihrer Elternteile aktiviert wird, oder Knoten, die von einem Elternteil aktiviert und von einem anderen deaktiviert werden, usw. Es ist ein ziemlich allgemeiner Rahmen zum Erstellen von Geschichten mit mehreren, voneinander abhängigen Threads.
quelle
Nach meinem Verständnis ist das, was Sie wollen, nicht nur eine Entscheidungsmaschine, sondern auch eine Regelmaschine. Für jede Entscheidung führen Sie eine Untergruppe von Regeln aus, die durch diese Entscheidung definiert wurden. Die Ausführung dieser Regeln hängt häufig vom Status bestimmter Entitäten ab, z. B. Ihres Baumbeispiels.
Wenn Ihr Player eine Entscheidung trifft, suchen Sie nach dieser Entscheidung, führen Sie die Regeln aus und stellen Sie dann die nächsten verfügbaren Entscheidungen wie gewohnt bereit. Ihre Regeln sind jedoch dahingehend dynamisch, dass einige von ihnen nur basierend auf anderen Regeln ausgeführt werden, die bereits ausgeführt wurden.
Einige mehr auf Wikipedia .
Aus der Unterüberschrift " Wann werden Regel-Engines verwendet ?" (Schwerpunkt liegt bei mir):
Zu beachten ist, dass eine Regel-Engine gelegentlich am besten mit einer vereinfachten domänenspezifischen "Sprache" oder so ähnlich wie YAML implementiert wird. Ich würde XML nicht vorschlagen.
quelle
Sie müssen berücksichtigen, dass ein Ereignis nicht nur auf Benutzerentscheidungen beruht. Wie Sie bemerkt haben, muss ein Ereignis angehängt werden, wenn eine Reihe von Entscheidungssequenzen getroffen werden, und dann wird etwas anderes angehängt (wie zwei Tage danach).
Was Sie meiner Meinung nach brauchen, ist eine Möglichkeit, Ereignisse zu modellieren und auszulösen. Während der erste eher an Ihren speziellen Fall gebunden ist, kann der letztere durch eine hierarchische Zustandsmaschine (HSM) modelliert werden, die Ihre Ereignisse direkt oder indirekt auslöst.
Denken Sie daran, dass eine Zustandsmaschine unter dem Fluch der Dimensionalität leidet, der nur durch eine hierarchische Struktur gemildert wird. Bald werden Sie verstehen, dass Sie die komplexe Bedeutung des Status mithilfe eines HMS modellieren, aber auch eine Möglichkeit zur Abfrage bereitstellen müssen.
In diesem Szenario gibt es grundlegende Ereignisse (Benutzerentscheidungen, Uhrzeit, Wetteränderungen usw.), die sowohl vom HSM als auch von grundlegenden Ereignisrückrufen verarbeitet werden. Das HSM bietet ein Modell für das "Gedächtnis" und die Rückrufe bieten eine Möglichkeit, zu beschreiben, wie dieses Gedächtnis verwendet werden muss, um die Folgen einer Folge von Entscheidungen / externen Ereignissen zu berechnen.
Möglicherweise verwenden Sie auch ein Diktonar (oder eine andere Sammlungsstruktur) von HMS, eines für jeden "Aspekt" des zu berechnenden Status. Ein Beispiel kann die Verwendung eines HMS-Ereignisses und eines Ereignisses für die Entscheidungen sein, die Rückrufe treffen, um Ereignisse auszulösen.
Alle diese Infrastrukturen dienen dem Zweck, das Verhalten eines menschlichen Dungeon-Meisters nachzuahmen: Er zeichnet im Allgemeinen die aktuelle Situation (HMS ["extern"]) aufgrund von Spielerentscheidungen und Umgebungsbedingungen im Kopf auf. Wenn sich etwas anhängt, kann es Entscheidungen anhand seiner mentalen Aufzeichnung treffen und auch einen internen Strategiestatus (HSM ["intern"]) aufzeichnen, um zu vermeiden, dass es in ähnlicher Weise reagiert, wenn sich beispielsweise eine Situation ergibt.
quelle