Blog Info Screens Videos Impressum/Datenschutz

Das Dialog- und Hilfesystem

Was wären Adventures ohne Gespräche mit anderen Charakteren? Neben verzwickten Rätseln tragen Konversationen zur Spannung und zum Fortschreiten des Spielgeschehens bei. Durch Gespräche kann man sich als Spieler in die Charaktere hinein versetzen und sich vielleicht sogar mit ihnen identifizieren. Aber wie setzt man so eine Konversation mit anderen Spielecharakteren um? Zwei bekannte Ansätze sind:

  • Das Spiel bietet dem Spieler mehrere Sätze an, die der Spielecharakter sagen kann (wie z.B. im Spiel "Monkey Island"). Der Spieler kann nun einen davon auswählen und der Geprächspartner reagiert anschließend entsprechend.
  • Man bietet dem Spieler die Gesprächsthemen an, über die er sich mit dem Gesprächspartner unterhalten kann und zwischen denen er wählen soll (wie z.B. in den Spielen "Baphomets Fluch" oder "Sam & Max Hit the Road"). Die Gesprächsthemen können dabei als Stichpunkte oder als Symbole angezeigt werden. Der weitere Gesprächsablauf zwischen Spielercharakter und Gesprächspartner verläuft dann automatisch.
Für die Geistfrei GmbH haben wir uns für den ersten Ansatz entschieden, da dieser mehr Möglichkeiten bietet, die Konversation witzig zu gestalten. Der Spieler sieht die Antwortmöglichkeiten, die Charles Stone in dem Moment durch den Kopf gehen und zwischen denen er sich entscheiden muss, um das Spielgeschehen voran zu treiben.

Um Dialoge zu planen, verwenden wir eine Art Flussdiagramm, in dem der komplette Dialogbaum mit den jeweiligen Reaktionen erfasst ist. Ein einfacher fiktiver Beispieldialog könnte so aussehen:


Die programminterne Umsetzung ist dann relativ einfach. Das komplette Dialogsystem besteht nämlich nur aus sechs Befehlen:
  1. StartConversation("Filename.dialog", "INIT");
  2. StopConversation();
  3. AddConversationItem(ITEM_ID, POS, "Text", "File.mp3", "NODE");
  4. RemoveConversationItem(ITEM_ID);
  5. RemoveAllConversationItems();
  6. ShowConversationItems();
  • StartConversation lädt eine Scriptdatei, die nach dem zuvor erstellten Flussdiagramm aufgebaut ist, in den Speicher. INIT definiert beim Starten des Dialogsystems den Einstiegsknoten (die ID eines Scriptblocks).
  • StopConversation stoppt den laufenden Dialog und schaltet das Spiel zurück in den normalen Spielmodus.
  • AddConversationItem fügt einen neuen Satz zur Auswahl hinzu. Dieser bekommt eine eindeutige ITEM_ID zugewiesen. Der zweite Parameter bestimmt die Position des Textes innerhalb der Auswahl. Anschließend folgen als Parameter der eigentliche Text, der gesagt werden soll und der Name der mp3-Datei, die den gesprochenen Text enthält. NODE gibt den Scriptblock an, der ausgeführt werden soll (siehe Beitrag "Aufbau einer Scriptdatei"), wenn dieser Satz vom Spieler ausgewählt wird.
  • RemoveConversationItem entfernt aus der Auswahlliste den Satz mit der eindeutigen ITEM_ID.
  • RemoveAllConversationItems entfernt alle zur Auswahl stehenden Sätze.
  • ShowConversationItems präsentiert schließlich alle aktuell möglichen Sätze auf dem Bildschirm, damit der Spieler zwischen ihnen wählen kann.
Für den oben abgebildeten Beispieldialog könnte die Dialogdatei somit wie folgt aussehen (die Konversation wird dabei z.B. vom aktuellen Szenenscript über StartConversation("Hank.dialog", "GREETING"); aufgerufen):

[GREETING]
    STONE: GotoActor(HANK);
    Wait();

    // Gesprächselemente hinzufügen:
    AddConversationItem(ID1, 1, "Hi!", "15.mp3", "HI_HANK");
    AddConversationItem(ID2, 2, "Hallo Hank!", "16.mp3", "HI_HANK");
    AddConversationItem(ID3, 3, "Wie geht's dir, Boss?", "17.mp3", "HOW_ARE_YOU");
    AddConversationItem(ID999, 999, "Mach's gut!", "18.mp3", "BYE1");

    // Gesprächselemente dem Spieler als Auswahl präsentieren:
    ShowConversationItems();
[END]

[HI_HANK]
    HANK: Say("Hallo. Mach dich nützlich und geh' wieder an die Arbeit!", "23.mp3");
    Wait();

    // nur Gesprächselement ID1 und ID2 aus der Auswahl entfernen:
    RemoveConversationItem(ID1);
    RemoveConversationItem(ID2);

    // die übrig gebliebenen Gesprächselemente darstellen:
    ShowConversationItems();
[END]

[HOW_ARE_YOU]
    HANK: Say("Wenn wir einen Auftrag bekommen würden, würde es mir besser gehen.", "64.mp3");
    Wait();

    // Alle Gesprächselemente entfernen, neue generieren und darstellen:
    RemoveAllConversationItems();
    AddConversationItem(ID4, 1, "Soll ich dir einen Kaffee bringen?", "54.mp3", "BYE2");
    AddConversationItem(ID5, 2, "Würde es dir vielleicht auch besser gehen, wenn ich dich umarme?", "98.mp3", "BYE3");
    AddConversationItem(ID999, 999, "Mach's gut!", "18.mp3", "BYE1");
    ShowConversationItems();
[END]

[BYE1]
    HANK: Say("Tschüß!", "63.mp3");
    Wait();

    // Dialogsystem beenden:
    StopConversation();
[END]

[BYE2]
    HANK: Say("Ja, und beeil dich!", "151.mp3");
    Wait();

    // Dialogsystem beenden:
    StopConversation();

    // Stone zur Tür gehen lassen:
    STONE: GotoActor(KITCHENDOOR);
    Wait();
[END]

[BYE3]
    HANK: Say("Geh zurück an die Arbeit!", "76.mp3");
    Wait();
    STONE: Say("Okay, Boss …");
    Wait();

    // Dialogsystem beenden:
    StopConversation();
[END]

Der Beginn des Dialogs mit Hank sieht dann am Bildschirm so aus:


In Wirklichkeit sind die Dialoge natürlich viel komplexer. 

Dialoge verwenden wir in "Geistfrei GmbH" auch als Hilfesystem. Dazu kann der Spieler jederzeit seinen Boss Hank per Mobiltelefon anrufen und ihn um Rat fragen, wenn er bei einem Rätsel nicht weiter kommt. Damit das Gespräch möglichst realistisch ist, sind auch die Diagramme dementsprechend komplex. Die Umsetzung des folgenden Hilfediagramms in eine Dialogdatei ist meine aktuelle Aufgabe. … und dass ich mich davor etwas drücke merkt man sicherlich an dem Umfang dieses Blog-Eintrags ;-)



Blog-Archiv

Labels