Каков наилучший способ реализовать систему дерева диалогов в моей игре? Я хочу, чтобы NPC дал игроку различные наборы ответов, некоторые из которых могут появиться только тогда, когда у игрока есть предмет или произошло предыдущее событие.
Каков наилучший способ реализовать систему дерева диалогов в моей игре? Я хочу, чтобы NPC дал игроку различные наборы ответов, некоторые из которых могут появиться только тогда, когда у игрока есть предмет или произошло предыдущее событие.
Ответы:
Деревья диалогов должны быть сделаны с использованием XML. Вы сохраняете условия для ответов и ответов во вложенных деревьях со ссылкой на файл сценария, если вам нужно сделать что-то более сложное.
Вы должны держать сценарии и диалоги отдельно, особенно если вы собираете RPG, у которой есть метрическая тонна разговоров. Затем вы можете использовать библиотеку типа simpleXML для чтения файла XML.
Схожий вопрос по SO с примером: https://stackoverflow.com/questions/372915/game-logic-in-xml-files
Я хотел бы изучить встраивание языка сценариев, такого как lua или ruby, и кодирование диалоговых взаимодействий в этом.
Таким образом, скрипт диалога может выглядеть так:
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!"
Это также хорошо работает для кодирования ИИ и других простых вещей, которые полезно настроить во время выполнения. Вы даже можете добавить редактор, встроенный в ваше приложение, который можно вызывать при запуске в режиме отладки (или в качестве пасхального яйца).
В игре Stendhal мы используем конечный автомат для реализации NPC.
На следующей диаграмме показан небольшой пример из руководства по написанию квестов .
В начале, NPC находится в состоянии ожидания и может ходить. Игрок может начать разговор, сказав «привет», и NPC перейдет в состояние ATTENDING. В этом состоянии он отвечает на вопросы о своей «работе» и предлагает игровую «помощь». Игрок может попросить квест, и NPC перейдет в состояние QUEST_OFFERED, ожидая, когда игрок примет («да») или отклонит («нет») его.
Мы определили набор условий, которые могут быть прикреплены к переходам. Например, завершение квеста возможно только в том случае, если выполнено PlayerHasItemWithHimCondition .
После выполнения перехода NPC может сказать какой-нибудь текст и / или выполнить действие. Подобно условиям, мы определили повторно используемый набор действий, такой как EquipItemAction, который используется, чтобы дать игроку награду за квест.
Несколько условий могут быть объединены с использованием AndCondition , OrCondition и NotCondition . Обычно по завершению квеста нужно выполнить ряд действий, поэтому есть и класс MultipleActions .
Хотя реальная реализация в Stendhal страдает от того, что ее трудно перевести на другие (человеческие) языки, я думаю, что общая концепция хороша.
Вы можете взглянуть на инструмент Dlgedit движка Open Source RPG Adonthell . Он очень продвинутый и должен содержать все, что вам нужно (включая источники;))
Я думаю, что для добавления в переводы вы все равно можете использовать XML для логики, как указано выше . Когда вы попадаете в такую сложность, вы должны написать свой собственный инструмент для диалога. Текст вашего диалога будет храниться как ключ к базе данных, которую вы можете поменять в зависимости от языка, который вы хотите отобразить.
Например, вы могли бы иметь:
<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>
Затем вам нужно было бы заменить текстовое средство визуализации квеста "Localize.FixMyCar" соответствующим образом переведенным текстом.
Ваш инструмент будет отображать то, что игрок увидит на выбираемом языке вместе с редактируемым необработанным XML.
Точно так же вы можете использовать что-то вроде этого из приведенного вами примера :
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
null,
ConversationStates.QUEST_OFFERED,
Localization[ "BringMeABeer" ],
null);
Если ваши ключи достаточно наглядны, отсутствие полного текста не должно быть проблемой.
Нечто подобное может быть полезным:
Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];
Данные управляют вашими персонажами с помощью скриптов LUA или даже файлов XML. Когда вы взаимодействуете с NPC, возьмите файл, который к нему прикреплен, прочитайте его, отрегулируйте любые игровые переменные, которые могли быть вызваны, и сгенерируйте правильный ответ.
Самый большой выигрыш от этого - то, что вы можете легко входить и манипулировать диалогом, добавлять новые символы и т. Д. Вы также избегаете путаницы в своей кодовой базе со специальной логикой в обработке каждого случая.
Если у вас довольно глубокий набор диалоговых деревьев, используйте ChatMapper . Они имеют полнофункциональную бесплатную версию, а инструмент позволяет вам экспортировать ваши диалоговые деревья в XML. Я использую его, и это отличный способ визуализации и организации сложных диалоговых деревьев.
Если ваши диалоги имеют какую-либо сложность, самое важное, что вам нужно для реализации диалога, - это способ понять сложность вашего взаимодействия. Я рекомендую некоторый редактор Node для визуализации этого, хотя у меня нет хороших открытых систем, чтобы рекомендовать.
Я думаю, что вы используете свой собственный язык сценариев для управления играми такого типа (если нет, то должны). Затем разверните свой сценарий для обработки диалогов.
Вы можете работать с другими игровыми переменными при создании логики диалогов. Игровые движки похожи на лего. Вы запрограммировали только кирпичи и скрипт использует их. Неважно, если вы сделаете какой-нибудь скрипт-интерпретатор или компилятор. Но скрипт всегда полезен.
Простой автомат может сделать:
(dialogueline_id, condition) -> (next_id, response)
Это может выглядеть примерно так:
(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!!!")
В игре вы найдете идентификатор и попробуйте сопоставить идентификатор и условие.
Вам нужно смоделировать условия и действия. По объектам, указателям на функции, XML ...
Хороший редактор диалогов тоже пригодится.