如何在游戏中实现对话框树?


51

在我的游戏中实现对话框树系统的最佳方法是什么?我希望NPC为播放器提供不同的响应集,其中一些响应仅在播放器具有一项或发生先前事件时才会出现。


2
《赏金》特别针对如何处理触发短语和NPC文本的翻译提供了好主意。这样,NPC可以根据发起对话的玩家理解和说不同的语言。即使使用gamedev.stackexchange.com/questions/31/…中的构建块方法,在文本存储库中包含逻辑似乎也不是一个好主意。但是拆分它们会使理解代码变得更加困难。
亨德里克·布鲁默曼

Answers:


17

对话框树应使用XML完成。如果需要执行更复杂的操作,则可以使用对脚本文件的引用将响应条件和响应条件存储在嵌套树中。

您应该将脚本和对话框分开,特别是如果您要组合一个具有数以吨计的会话的RPG。然后,您可以使用诸如simpleXML之类的库来读取XML文件。

在SO上有一个类似的问题,举一个例子:https : //stackoverflow.com/questions/372915/game-logic-in-xml-files


为XML +1。这比嵌入代码本身要好得多,它允许更改而无需重新编译代码,并且是一些强大的编辑器可以读取的标准格式。
AttackingHobo 2010年

34
XML只是一种格式(IMO是一种不好的格式)。这个答案的意思是,“创建一种包含基本逻辑和流程,但主要由您的对话组成的小型领域语言,并进行解析。” 以一般的方式,我同意这个答案。
Ipsquiggle 2010年

5
确实,XML只是容器,您也可以使用Lua或其他脚本语言(也更加人性化和可编辑性)来实现它。
LearnCocos2D 2010年

4
XML解析成本很高,并且占用大量内存。可以将其用作存储格式很好,但是我会编写实用程序,将对话框树转换为运行时使用的二进制格式。如果您在PC上不关心内存使用情况,可能没问题,但是在任何其他平台上,内存成本都会使您大失所望。
BigSandwich

1
-1(表示XML)。我同意@Ipsquiggle和@BigSandwich
o0'。

20

我将研究嵌入诸如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!"

这也适用于对AI和其他在运行时进行调整有用的简单代码进行编码。您甚至可以在应用程序中添加内置的编辑器,当在调试(或作为复活节彩蛋)中运行时可以调用该编辑器。


1
我更喜欢直接XML,因为您可以添加逻辑。但是我要说的是,文本本身可能应该是XML而不是代码。(更易于编辑,本地化为其他语言等)。
伊恩

如果您需要本地化/更轻松的编辑,则可以将文本包装在一个函数中,该函数将附带的文本写入一个单独的文件中,例如Qt中的tr(QString)函数/宏。pepper.troll.no/s60prereleases/doc/linguist-hellotr.html
Nailer

是什么让您无法使用xml中的属性或额外标签在此处模拟逻辑?
lathomas64 2010年

16

在游戏Stendhal中,我们使用有限状态机来实现NPC。

下图显示了如何编写任务教程的一个小例子。

FSM状态为IDLE,ATTENDING和QUEST_OFFERED

最初,NPC处于空闲状态,并且可能正在走动。玩家可以说“嗨”开始对话,然后NPC进入“注意”状态。在这种状态下,它回答有关他的“工作”的问题,并提供一些游戏“帮助”。玩家可能会要求一个任务,并且NPC将进入状态QUEST_OFFERED,等待玩家接受(“是”)或拒绝(“否”)。

我们定义了一可以附加到转换的条件。例如,只有满足PlayerHasItemWithHimCondition才可能完成任务。

执行转换后,NPC可能会说一些文本和/或执行一个动作。与条件类似,我们定义了一组可重复使用的动作,例如EquipItemAction,用于为玩家提供任务奖励。

可以使用AndConditionOrConditionNotCondition组合多个条件。通常,在完成任务时需要执行许多操作,因此也有MultipleActions类。

尽管在Stendhal中的实际实现方式很难在其他(人类)语言中翻译,但我认为总体概念还是不错的。



5

我认为,在翻译中加入,你仍然可以使用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>" ];

4

数据通过LUA脚本甚至XML文件来驱动您的角色。与NPC互动时,请抓取附加到该NPC的文件,将其读入,调整可能已触发的任何游戏变量,并产生有效的响应。

通过这种方式获得的最大好处是,您可以轻松地进入并操纵对话框,添加新字符等。您还可以避免在处理每种情况时使用特殊的逻辑来破坏代码库。


1
是Lua,不是LUA。:)
RCIX

2
我只是为你做的,伙计。;)
David McGraw

4

如果使用XML,请确保您构建了一个小的工具来编辑XML文件。否则你会发疯的。


如果还没有编辑它的工具,那么首先使用它是没有意义的:还可以创建自己的格式!
o0'。

3

如果您有相当深的对话框树集,请使用ChatMapper。它们具有功能齐全的免费版本,该工具允许您将对话框树导出为XML。我一直在使用它,它是可视化和组织复杂对话框树的绝佳方法。


1

如果您的对话框非常复杂,那么实现对话框所需的最重要的事情就是理解交互的复杂性。我建议使用某种类型的Node编辑器来可视化它,尽管我没有任何好的开放系统值得推荐。


1

我认为您可以使用自己的脚本语言来指导这些类型的游戏(如果不是,则应该这样做)。然后也扩展您的脚本以进行对话框处理。
在创建对话框逻辑期间,您可以使用其他游戏变量。游戏引擎就像乐高游戏。您仅编程了砖,脚本使用了它们。是否制作一些脚本解释器或编译器都没有关系。但是脚本总是有用的。


0

简单的自动机可以做到:

(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!!!")

在游戏中,您找到id并尝试匹配id和条件。

您需要对条件和动作进行建模。通过对象,函数指针,XML ...

好的对话编辑器也会很方便。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.