Jak mogę wdrożyć drzewa dialogowe w mojej grze?

51

Jaki jest najlepszy sposób na wdrożenie systemu drzew dialogowych w mojej grze? Chcę, aby NPC dał graczowi różne zestawy odpowiedzi, niektóre z nich mogą pojawić się tylko wtedy, gdy gracz ma przedmiot lub miało miejsce poprzednie zdarzenie.

Bryan Denny
źródło
2
BOUNTY jest szczególnie dobrym pomysłem, jak radzić sobie z tłumaczeniem zdań wyzwalających i tekstu NPC. Aby NPC mógł zrozumieć i mówić różnymi językami w zależności od gracza, który rozpoczął rozmowę. Nawet przy podejściu opartym na elementach konstrukcyjnych w gamedev.stackexchange.com/questions/31/... logika w repozytoriach tekstowych nie wydaje się dobrym pomysłem. Ale podział ich znacznie utrudnia zrozumienie kodu.
Hendrik Brummermann

Odpowiedzi:

17

Drzewa dialogowe należy wykonywać przy użyciu XML. Warunki odpowiedzi i odpowiedzi są przechowywane w zagnieżdżonych drzewach z odniesieniem do pliku skryptu, jeśli trzeba zrobić coś bardziej złożonego.

Powinieneś oddzielić skrypty i dialogi osobno, szczególnie jeśli tworzysz RPG o tonie konwersacji. Następnie możesz użyć biblioteki takiej jak simpleXML, aby odczytać plik XML.

Podobne pytanie dotyczy SO z przykładem: https://stackoverflow.com/questions/372915/game-logic-in-xml-files

Lis
źródło
+1 dla XML. Znacznie lepiej niż osadzanie w samym kodzie, pozwala na zmiany bez ponownej kompilacji kodu i jest standardowym formatem, który może być odczytany przez niektóre potężne edytory.
AttackingHobo
34
XML to tylko format (i, IMO, zły). Naprawdę to, co mówi ta odpowiedź, brzmi: „Utwórz mały język domeny, który zawiera podstawową logikę i przepływy, ale przede wszystkim składa się z twojego dialogu i go parsuje”. W ten ogólny sposób zgadzam się z tą odpowiedzią.
Ipsquiggle
5
Dokładnie, XML jest tylko kontenerem, możesz równie dobrze (i zdecydowanie bardziej czytelny i edytowalny przez człowieka) zaimplementować to za pomocą Lua lub innych języków skryptowych.
LearnCocos2D,
4
XML jest parsowany i zajmuje dużo pamięci. Można używać go jako formatu pamięci, ale napisałbym narzędzie, które konwertuje drzewa okien dialogowych do formatu binarnego używanego w czasie wykonywania. Jeśli korzystasz z komputera i nie przejmujesz się zużyciem pamięci, może być w porządku, ale na każdej innej platformie koszt pamięci cię obciąży.
BigSandwich,
1
-1 dla XML. Zgadzam się z @Ipsquiggle i @BigSandwich
o0 '.
20

Chciałbym osadzić w tym język skryptowy, taki jak lua lub ruby, i interakcje w dialogu kodowania.

Tak więc skrypt okna dialogowego może wyglądać następująco:

switch showDialog "Why don't you just leave me along!", "Okay", "But I found your dog!"
    case 1:
        showDialog "And stay gone!"
    case 2:
        if playerHasObject "dog"
            showDialog "Thank you!"
        else
            showDialog "Liar!"

Działa to również dobrze do kodowania AI i innych prostych rzeczy, które są przydatne do poprawiania w czasie wykonywania. Możesz nawet dodać edytor wbudowany w aplikację, który można wywoływać podczas uruchamiania w trybie debugowania (lub jako Pisanka).

BarrettJ
źródło
1
Wolę to od prostego XML, ponieważ można dodać logikę. Powiedziałbym jednak, że sam tekst powinien być raczej w formacie XML niż w kodzie. (łatwiejsza edycja, lokalizacja na inne języki itp.).
Iain
jeśli potrzebujesz lokalizacji / łatwiejszej edycji, możesz zawinąć tekst w funkcję, która zapisuje załączony tekst w osobnym pliku, takim jak funkcja / makro tr (QString) w Qt. pepper.troll.no/s60prereleases/doc/linguist-hellotr.html
Nailer
co powstrzyma cię przed użyciem atrybutów lub dodatkowych tagów w xml do symulacji tutaj logiki?
lathomas64
16

W grze Stendhal używamy skończonej maszyny stanów do implementacji postaci niezależnych.

Poniższy diagram pokazuje mały przykład z pisania samouczka z zadaniami .

FSM ze stanami IDLE, ATTENDING i QUEST_OFFERED

Na początku NPC jest w stanie BIEGU bezczynnego i może chodzić. Gracz może rozpocząć rozmowę mówiąc „cześć”, a NPC przejdzie do stanu UCZESTNICTWO. W tym stanie odpowiada na pytania dotyczące jego „pracy” i oferuje „pomoc” do gry. Gracz może poprosić o misję, a NPC przejdzie do stanu QUEST_OFFERED, czekając, aż gracz zaakceptuje („tak”) lub odrzuci („nie”).

Zdefiniowaliśmy zestaw warunków, które można dołączyć do przejść. Na przykład ukończenie zadania może być możliwe tylko wtedy, gdy zostanie spełniony parametr PlayerHasItemWithHimCondition .

Po wykonaniu przejścia NPC może powiedzieć tekst i / lub wykonać akcję. Podobnie do warunków, które zdefiniowaliśmy, zestaw działań wielokrotnego użytku, takich jak EquipItemAction, który służy do przyznania nagrody za zadanie graczowi.

Wiele warunków można łączyć za pomocą AndCondition , OrCondition i NotCondition . Zwykle po zakończeniu zadania należy wykonać szereg akcji, więc istnieje również klasa MultipleActions .

Chociaż rzeczywista implementacja w Stendhal cierpi z powodu braku możliwości łatwego tłumaczenia na inne (ludzkie) języki, myślę, że ogólna koncepcja jest dobra.

Hendrik Brummermann
źródło
5

Możesz rzucić okiem na narzędzie Dlgedit w silniku Open Source RPG Adonthell . Jest bardzo zaawansowany i powinien zawierać wszystko, czego potrzebujesz (w tym źródła;))

Koonsolo
źródło
5

Myślę, że do dodawania tłumaczeń nadal można użyć XML do logiki, jak podano powyżej . Kiedy wchodzisz w tego rodzaju złożoność, powinieneś napisać własne narzędzie dialogu. Twój tekst dialogowy zostanie zapisany jako klucz do bazy danych, którą możesz wymienić w zależności od języka, który chcesz wyświetlić.

Na przykład możesz mieć:

<dialogue id="101" condition="!npc.carsFixed">
  <message>Localize.FixMyCar</message>
  <choices>
    <choice condition="hero.carFixingSkill > 5" priority="7" id="Localize.Sure">
      <command>hero.carFixingSkills += 1</command>
      <command>npc.carFixed = true</command>
      <command>hero.playSmokeAnimation()</command>
      <command>nextDialogue = 104</command>
    </choice>
    <choice condition="hero.carFixingSkill <= 5" id="Localize.CantFix">
      <command>nextDialogue = 105</command>
    </choice>
    <choice id="Localize.FixYourself">
      <command>npc.likesHero -= 1</command>
    </choice>
  </choices>
</dialogue>

Wówczas renderer tekstu zadania zastąpiłby „Localize.FixMyCar” odpowiednio przetłumaczonym tekstem.

Twoje narzędzie wyświetlałoby to, co odtwarzacz zobaczyłby w wybranym języku obok edytowalnego surowego XML.

Podobnie możesz użyć czegoś takiego z podanego przykładu :

npc.add(ConversationStates.ATTENDING,
        ConversationPhrases.QUEST_MESSAGES, 
        null,
        ConversationStates.QUEST_OFFERED, 
        Localization[ "BringMeABeer" ],
        null);

Jeśli twoje klucze są wystarczająco opisowe, brak pełnego tekstu nie powinien być problemem.

Przydałoby się coś takiego:

Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];
Toddw
źródło
4

Dane napędzają twoje postacie za pomocą skryptów LUA, a nawet plików XML. Kiedy wchodzisz w interakcję z NPC, weź dołączony do niego plik, przeczytaj go, dostosuj wszystkie zmienne gry, które mogły zostać wyzwolone, i uzyskaj prawidłową odpowiedź.

Największą korzyścią z robienia tego w ten sposób jest to, że możesz łatwo wejść do okna dialogowego i manipulować nim, dodawać nowe znaki itp. Unikasz również zepsucia bazy kodu dzięki specjalnej logice obsługi każdego przypadku.

David McGraw
źródło
1
To Lua, nie LUA. :)
RCIX
2
Zrobiłem to tylko dla ciebie, stary. ;)
David McGraw,
4

Jeśli używasz XML, upewnij się, że zbudowałeś małe narzędzie do edycji pliku XML. W przeciwnym razie oszalejesz.

zooropa
źródło
Jeśli nie ma już narzędzia do jego edycji, to nie ma sensu używać go w pierwszej kolejności: utwórz również własny format!
o0 ”.
3

Jeśli masz dość głęboki zestaw drzew dialogowych, użyj ChatMapper . Posiadają w pełni funkcjonalną bezpłatną wersję, a narzędzie pozwala na eksport drzew dialogowych do formatu XML. Korzystam z niego i jest to doskonały sposób na wizualizację i organizację złożonych drzew dialogowych.


źródło
1

Jeśli Twoje okna dialogowe są dowolnej złożoności, najważniejszą rzeczą, której potrzebujesz do implementacji okien dialogowych, jest sposób na zrozumienie złożoności interakcji. Polecam jakiegoś edytora węzłów, aby to zwizualizować, chociaż nie mam dobrych dobrych systemów otwartych do polecania.

Aaron Brady
źródło
1

Myślę, że używasz własnego języka skryptowego do kierowania tego typu grą (jeśli nie, powinieneś). Następnie rozwiń skrypt do obsługi okien dialogowych.
Możesz pracować z innymi zmiennymi gry podczas tworzenia logiki dialogów. Silniki gier są jak Lego. Zaprogramowałeś tylko cegły, a skrypt ich używa. Nie ma znaczenia, czy wykonasz interpreter skryptów lub kompilator. Ale skrypt jest zawsze przydatny.

samboush
źródło
0

Prosty automat może wykonać:

(dialogueline_id, condition) -> (next_id, response)

Może to wyglądać mniej więcej tak:

(1, troll is hungry?) -> (2, say "troll be hungry")
(2, player has bananas?) -> (3, say "hey, you have bananas!")
(3, ) -> (-1, (say "i like bananas, i take them and eat, you may pass, bye", remove bananas, feed the troll))
(2, player does not have bananas?) -> (-1, say "go away!!!")

W grze znajdziesz identyfikator i spróbuj dopasować identyfikator i warunek.

Musisz wymodelować warunki i działania. Według obiektów, wskaźników funkcji, XML ...

Przyda się również dobry edytor dialogów.

użytkownik712092
źródło