Dialog System

In vielen Spielen werden Dialoge für Erklärungen oder Interaktionen mit dem Spieler genutzt. Wir wollen nun in Construct 3 ein Dialogsystem erstellen, welches für alle möglichen Spielen genutzt werden kann.

Hier kann das fertige Construct 3 Projekt heruntergeladen und selbst ausprobiert werden:

Idee

Der Spieler kann sich frei auf der Karte bewegen. Wenn der Spieler einen NPC ( Nichtspielercharakter) berührt und die Enter-Taste drückt, soll ein Dialogfeld auftauchen. Der Inhalt des Dialogfeldes wird aus einer JSON Datei geladen. Jeder Dialog kann mehrere Zeilen lang sein und endet, wenn alle Zeilen nacheinander im Dialogfeld dargestellt wurden.

JSON

Die Inhalte der Dialoge könnte man in Variablen oder Listen speichern, doch müsste man dann immer zwischen diesen hin- und herspringen und auch ein aktualisieren ist nicht so einfach. Wenn man später auch noch das Spiel in verschiedenen Sprachen veröffentlichen will, wäre das mit Variablen sehr umständlich.

Am einfachsten ist die Nutzung einer externen JSON Datei, die den Inhalt der Dialoge hat. Dann reicht es aus diese Datei zu bearbeiten und automatisch passen sich alle Dialoge im Spiel dieser Datei an. Auch verschiedene Dateien für verschieden Sprachen sind nutzbar.

Mit Hilfe eines Online JSON Editors kann man die Dialogdatei recht einfach befüllen. Hier die JSON Dialog Datei aus dem Construct 3 Beispiel:

[
  {
    "npcId": 0,
    "npcName": "Richi",
    "dialogs": [
      {
        "line": "Hallo Playername."
      },
      {
        "line": "Das ist ein einfaches Dialogsystem. /brDas System lädt den Dialog aus einer JSON Datei und gibt diesen dann Zeile für Zeile hier wieder."
      }
    ]
  },
  {
    "npcid": 1,
    "npcName": "Sarah",
    "dialogs": [
      {
        "line": "Hallo mein Name ist Sarah. Ich bin gerade 8 Jahre alt geworden und turne gerne am Kletterseil!"
      },
      {
        "line": "Ich habe eine Roboterkatze in Lego gebaut und ein Lego Friends Schwimmbad."
      }
    ]
  },
  {
    "npcid": 2,
    "npcName": "Simon",
    "dialogs": [
      {
        "line": "Bäm bäm ich bin Simon!"
      },
      {
        "line": "Ich spiele gerne Fortnite und mache fleißig meine Hausaufgaben."
      }
    ]
  }
]

In diesem Beispiel gibt es 3 verschiedene „Dialoge“. Jeder Dialog hat eine ID von einem NPC und dessen Namen. Diese ID wird mit den NPC Objekten im Construct 3 Editor und einer passenden ID Variablen verbunden:

Der grüne NPC Platzhalter hat die NpcID Variable mit dem Wert 2. Wenn man dies mit der JSON Datei von oben vergleicht, sieht man, dass das der NPC Simon ist.

Um die JSON Dialog Datei anzupassen, kann man folgenden JSON Editor nutzen. Dazu kopiert man den JSON Code von oben, fügt diesen in den Editor ein und kann dann den Code einfach bearbeiten.

Programmierung in Construct 3

Benötigte Variablen

Zuerst erstellen wir ein paar Variablen, die wir für das Dialogsystem benötigen:

  • curDialog = speichert die aktuelle Zeile des Dialogs.
  • curNpcID = wird bei der Berührung mit einem NPC gesetzt und sagt dem Programm, welcher Dialog angezeigt werden soll.
  • GameState = diese Variable ist entweder leer oder mit „dialog“ gefüllt. Diese Variable wird immer getestet, um zu wissen, ob der Player gerade einen Dialog führt oder nicht. Wenn nicht, dann kann sich der Player bewegen und andere Dinge machen.
  • typewriterFinished = hält den Überblick ob der Typewriter Effekt unseres Dialogs fertig ist oder nicht. Wenn dieser fertig angezeigt wurde, ist die aktuelle Zeile fertig und rechts unten beim Dialog erscheint ein Pfeil nach unten, damit der Spieler die nächste Zeile aufrufen kann.

Start des Layouts

Beim Start des Layouts wird die JSON Datei in ein JSON Objekt geladen.

Every Tick

Bei der Every Tick Gruppe wird zuerst geschaut ob die Variable „GameState“ gleich „dialog“ ist, wenn ja, dann kann sich der Spieler nicht mehr bewegen.

Des Weiteren wird immer abgefragt, ob beim Textfeld „txtDialog“ der Typewriter Effekt fertig ist, wenn ja, dann soll er den „Pfeil nach unten“ anzeigen, 0,2 Sekunden warten und dann die Variable „typewriterFinished“ auf true setzen. Diese Variable benötigen wir noch, um festzustellen, ob die Enter Taste während dem Typewirter Effekt oder danach gedrückt wird.

Dialog Control

Bei der Gruppe Dialog control wird überprüft, ob der Spieler die Enter Taste gedrückt hat, wenn ja, wird mit Hilfe der „Is overlapping“ Methode geschaut, ob ein NPC berührt wird. Wenn ja wird die NpcID in der Variablen curNpcID gespeichert.

Wird dieser NPC berührt und die Variable GameState ist „“ also leer, wird diese mit „dialog“ gefüllt.

Beim nächsten Block wird geschaut, ob die Enter Taste gedrückt wird während der Text mit Hilfe des Typewriter Effekts gerade ins Dialogfeld geschrieben wird, wenn ja, dann zeigen den Text sofort komplett an.

Der Hauptcode danach testet, ob die Variable GameState gleich „dialog“ ist und ob der Typewriter Effekt zu Ende ist, wenn ja, wir die Funktion „DisplayDialog“ mit dem Parameter curDialog, also mit der aktuell anzuzeigenden Dialogzeile aufgerufen. Zugleich wird hier getestet, ob es die letzte Zeile des Dialogs war, wenn ja, wird der Dialog danach beendet.

Dialog Functions

Das Projekt benötigt folgende Funktionen:

DisplayDialog

Die Funktion gibt die aktuell anzuzeigende Zeile des Dialogs zurück. Als Parameter wird die aktuelle Zeile (curDialog) und die ID des NPC (curNpcID) benötigt, um im JSON Objekt die richtige Zeile herauszufinden.

DialogFormat

Diese Funktion ist sehr interessant, da sie eine Zeile des Dialogs aufnimmt und nach verschiedenen Zeichen sucht, die dann ersetzt werden. Aufgerufen wird die Funktion in der vorherigen Funktion „DisplayDialog“ und dieser wird die aktuelle Zeile des Dialogs gegeben. Dann wird geschaut, ob in der Zeile z.B.: ein „/br“ auftaucht, wenn ja, wird dieses mit „newline“ – also einem Zeilenumbruch ersetzt:

// Zeile vor der Bearbeitung durch "DialogFormat"
"Das ist ein einfaches Dialogsystem. /brDas System lädt den Dialog aus einer JSON Datei und gibt diesen dann Zeile für Zeile hier wieder."

// Ergebnis:
Das ist ein einfaches Dialogsystem.
Das System lädt den Dialog aus einer JSON Datei und gibt diesen dann Zeile für Zeile hier wieder.

In diese Funktion kann man alle möglichen verschiedenen Zeichen oder Zeichenketten erweitern. Es ist sogar möglich, eine weitere Funktion anhand einer Zeichenkette aufzurufen. Siehe „Function maps“

GetNumLines

Diese Funktion gibt einfach die Anzahl der Dialogzeilen anhand der ID des aktuellen NPC zurück. Dies wird benötigt um zu testen, ob der Dialog zu Ende ist oder nicht.

EndDialog

Die Funktion setzt die Variable curDialog und GameState zurück, fügt der NPC Variable TimesSpokenTo 1 hinzu und versteckt den Dialog Layer.

Das wars auch schon. Dieses einfache Dialogsystem kann man nun seinen Construct 3 Spiele hinzufügen.

Links