如何在RPG游戏中处理多个故事线索?


26

我设计了一款具有多个故事线索的RPG游戏,这意味着,根据用户的选择,某些事情可能会或可能不会发生,您可以通过多种方式实现同​​一件事,结局可能会有所不同等等。

我实现了一个简单的决策引擎,该引擎运行良好,但存在一个巨大缺陷,当您做出决定时,故事会立即受到您的决定的影响,这意味着您无法做出会在不久的将来影响您的决定。这是因为故事像树形结构中的分支一样展开,并且始终需要知道下一个节点。在幕后,决策是使用队列来实现的:每个节点都知道上一个节点和下一个节点(或者如果它是一个决策节点,它将等待用户输入以设置下一个节点)

我看到很多具有复杂决策引擎的游戏,但我想知道它们是如何制作的?是否有使事情变得真正简单的特殊设计?有没有人做过类似的事情,可以给我提示如何解决这个问题?

更新1:

一个重要方面是设法以某种方式保持故事代码独立,以便可以从外部文件操纵它。我计划将其用作引擎,因此即使可能的选择也必须来自外部文件。该代码必须是完全抽象的。

另外,我对设计解决方案感兴趣,这是一种很好的解决方案,其他人是如何做到或做到的。


1
做出重要决策后,只需在全局可访问变量中跟踪它们即可(这些变量的数组将更易于管理)。然后,游戏程序的后续部分可以引用这些变量,以适当地操作或显示事物。例如,玩家决定种一棵小树,后来那棵树显得很大-如果他们不种那棵树,那棵树根本不会在游戏的同一时间出现。
兰道夫·理查森2011年

是的,这是我最初要做的,但是,我需要使它独立于代码。这意味着可以从外部文件完全操纵故事。因此,我必须找到一种方法来概括您刚才所说的内容,并以某种方式做到这一点,以使我不会失去对该项目的控制权(有很多决定)。将更新问题。谢谢!
Valentin Radu

因此,更具体地说,我无法检查if (isTree)或保留isTree全局变量,因为故事可能有也可能没有这种选择。明白我的意思了吗?它更像是一个选择引擎,可以提供多个故事。
Valentin Radu

另一个问题是,如果用户决定种植一棵我们设置的树,isTree=true但是后来,他做了其他事情,例如与一个同学打架,而后者却在树还很年轻的时候砍掉了他的树。因为他的屁股被踢了。现在,我们有2个变量影响树isTree==true' and didFightBrat == false` 的存在。明白我的意思了吗?而且链条可以永远持续下去,树的存在会受到未知数因素的影响。明白我的意思了吗?
Valentin Radu

然后将该数据存储在磁盘上的文件中。您需要创建两个子例程来加载和保存信息,然后根据需要使用代码各部分中的那些例程。
兰道夫·理查森2011年

Answers:


18

您还可以将队列概括为有向无环图(DAG)。您可以在Wikipedia上阅读有关这些内容的信息。基本上,每个节点可以有一个或多个“依赖”的父节点。不允许循环,即如果A依赖B,则B不能依赖A(直接或通过其他节点的任何间接链)。

每个节点都处于“活动”或“非活动”状态,并且仅当其所有父节点都已经活动时才被允许变为活动状态。图的结构(节点位于何处以及它们如何连接)是游戏数据的一部分,但活动/不活动状态是玩家保存数据的一部分。

这样,您可以对以下事物进行建模:植树时,将任务“ plantedTree”标记为活动;然后,在游戏的稍后部分,另一个任务“ treeGrown”将“ plantedTree”和某个其他节点(故事的一部分)都命名为其父节点。然后,“ treeGrown”仅在玩家到达故事中的该点时激活,并且“ plantedTree”也激活。

您可以包括其他功能,例如,如果某个节点的任何一个父节点激活,则激活的节点;或者被一个父节点激活而又被另一父节点取消激活的节点,等等。这是一个用于创建具有多个相互依赖线程的故事的通用框架。


一个很好的答案,谢谢。它实际上也解决了我遇到的其他问题,例如保存用户进度。这就是我所需要的。
Valentin Radu

@NathanReed为什么这不是周期性的?非循环通常不是图形的功能,而是图形设计的副产品。我不会出于这种意图而创建它。例如,假设您想让树识别季节。它们天生具有周期性,根据一个季节中可用的选择,您的故事情节可能相同。

它必须是非循环的,因为如果存在一个循环,则在试图找出循环中的某个节点是否可以活动时会陷入无限循环,因为您需要递归检查其所有祖先,包括该节点本身。如果您想对诸如季节之类的东西进行建模,则在此图表的背景下我不会这样做。
内森·里德

@NathanReed啊,对不起,我错过了递归部分。

3

据我了解,您想要的不仅是决策引擎,还有规则引擎。对于每个决策,您将执行该决策定义的规则的子集。这些规则的执行通常取决于某些实体的状态,例如您的树示例。

基本上,当玩家做出决定时,您会搜索该决定,执行规则,然后像正常一样提供下一组可用的决定。但是,您的规则是动态的,因为其中的一些规则只会根据已经执行的其他规则执行。

维基百科上有更多内容

从其“ 何时使用规则引擎”副标题(重点是我的):

  • 对于传统代码来说,这个问题太复杂了。
  • 该问题可能并不复杂,但是您看不到构建它的可靠方法。
  • 这个问题超出了任何明显的基于算法的解决方案。
  • 这是一个复杂的问题。没有明显的传统解决方案,或者问题没有得到充分理解。
  • 逻辑经常变化
  • 逻辑本身可能很简单,但是规则却经常更改。在许多组织中,软件发行很少见,规则可以帮助以合理安全的方式提供所需和期望的“敏捷性”。
  • 领域专家和业务分析师很容易获得,但不是技术性的。
  • 领域专家通常是有关业务规则和流程的丰富知识。它们通常是非技术性的,但可能非常合逻辑。规则可以使他们用自己的术语表达逻辑。当然,他们仍然必须批判性思考并具有逻辑思维能力。许多非技术职位的人都没有接受过形式逻辑方面的培训,因此请当心并与他们一起工作。通过将业务知识整理成规则,您通常会暴露出当前对业务规则和流程的理解方式上的漏洞。

需要注意的一件事是,有时最好使用简化的特定于域的“语言”或类似YAML的方法来实现规则引擎。我不建议使用XML。


1

您必须考虑一个事件并非完全基于用户的决定。如您所述,如果在执行一组决策序列时必须追加一些事件然后再追加其他内容(例如两天后)。

我认为您需要的是一种对事件建模和触发它的方法。尽管前者更多地取决于您的特定情况,但后者可以由直接或间接触发您的事件的分层状态机(HSM)建模。

请记住,状态机会遭受只能通过层次结构缓解的维数诅咒。很快,您将了解到,您需要使用HMS对状态的复杂含义进行建模,而且还需要提供一种查询状态的方法。

在这种情况下,您具有由HSM和基本事件回调处理的基本事件(用户决策,时间,天气变化等)。HSM为“内存”提供了一个模型,而回调提供了一种方法来描述如何必须使用该内存来计算一系列决策/外部事件的后果。

您还可能最终会使用HMS的字典(或其他收集结构),即您必须计算的每个状态的“方面”。一个示例可能是使用与HMS事件相关的事件,并为回调采取措施以触发事件。

所有这些基础设施的目的是模仿人类地牢大师的行为:由于玩家的决定和环境条件,他通常会记录下当前的状况(HMS [“外部”]);当附加某些东西时,它可以使用其心理记录进行决策并记录一些内部策略状态(HSM [“ internal”]),以避免例如附加某些情况时以类似的方式做出反应。

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.