管理游戏中活动的最佳方法?


13

我正在开发一款游戏,该游戏需要偶尔进行一些游戏内事件。一个很好的例子是教程。您开始游戏,并且在游戏中的几个点发生了一个事件:

  • 您遇到第一个敌人,游戏暂停,并且您收到关于如何杀死它的解释。
  • 您杀死了第一个敌人,您收到一条“好工作”消息。
  • 您将获得一个新项目,即带有项目统计信息弹出菜单。
  • 等等等

我正在研究的游戏是一款益智游戏,其游戏规则几乎相同,因此将所有这些事件单独编码为单独的级别似乎效率不高。

我应该以某种方式在XML等外部源中定义这些事件吗?然后编写一个解释器,以读取XML并设置级别的事件要求?我不确定如何定义一个事件,例如在杀死两个敌人时应该发生的事件。

需要明确的是,我并不是在寻找最佳的编程语言或脚本语言来执行此操作,而是在寻找最佳的处理方法。

谢谢!


编辑: 由于我的问题很难理解的第二个例子:

我遇到的问题是要以总是几乎相同的过程在游戏中添加一些额外的动作。就像RPG战斗一样,每个人都有转弯,选择技巧等-总是一样。但是,如果我想在两者之间显示过场动画,该怎么办?修改整个游戏结构,使其在包含过场动画的情况下进入经过改变的战斗等级,似乎效率很低。我想知道这通常是怎么做的。


8
不要过度概括,例如教程非常具体,并且附带许多不同的触发器/事件。硬编码/脚本没错。
Maik Semder 2011年

1
@Maik如果将其放入答案ID +1中,则简单易解决比每天都好。
詹姆斯

您的第二个示例更加清楚地表明抽象消息传递系统将是一个巨大的胜利。对于教程,您可以对事情进行硬编码,因为事情一开始就只发生一次,但是对于在整个游戏过程中随时都可能发生的持续事件,情况有所不同。
2011年

它仍然含糊不清,请列出3种不同过场动画的至少3个触发器。通常很难回答。基本上,您必须找到一种通用模式以了解如何最好地实施它。
Maik Semder 2011年

你想要什么?您要暂停操作并执行其他操作,然后取消暂停操作吗?
user712092 2011年

Answers:


7

这很大程度上取决于事件在游戏中对象之间的实际通信方式。例如,如果您使用的是中央消息传递系统,则可以有一个教程模块,该模块侦听某些消息并在听到某些消息时创建教程弹出窗口。然后,您可以在XML文件或教程模块解析的内容中设置要侦听的消息以及要显示的弹出窗口。通过拥有一个监视游戏状态并在游戏中注意到东西时显示教程弹出窗口的单独的教程对象,您可以随意更改教程对象,而无需更改游戏中的任何其他内容。(这是Observer模式吗?我对所有设计模式都不熟悉。)

总体而言,是否值得为此担心,取决于您教程的复杂性。在我的代码和/或级别中对事件进行硬编码对于我来说似乎并不重要,因为仅出现了一些教程弹出窗口。我很好奇您到底有什么想法会使您觉得它效率低下,因为您应该做的每个触发器都只是将一条消息发送到了教程模块,就像TutorialModule.show(“ 1st_kill”);


我认为,由于这是一款益智游戏,因此他的逻辑位于多个级别的一个位置,因此,如果我们为此做一个教程,就应该做一遍遍。老实说,如果它是一款益智游戏,即使它不是最漂亮的代码,我也不认为这会给它带来巨大的冲击,并且最终,在发行的游戏中起作用的代码总是-总是-比从来没有见过的漂亮代码好100%;)
詹姆斯(James

从来没有想过像观察者模式这样的东西,听起来像是一个不错的解决方案。我会尝试一下,谢谢:)
omgnoseat 2011年

7

据我了解,这是设计约束:

  1. 核心游戏代码并不关心关卡要求,也不应与处理它们的代码耦合。

  2. 同时,这是核心游戏代码,知道何时满足这些要求的特定事件发生(获取物品,杀死敌人等)。

  3. 不同级别有不同的要求集,需要在某处进行描述。

有了这些,我可能会做这样的事情:首先,制作一个代表游戏关卡的类。它将封装一个级别具有的一组特定要求。它具有可以在发生游戏事件时调用的方法。

给核心游戏代码提供对当前关卡对象的引用。当游戏事件发生时,它会通过调用它的方法告诉级别:enemyKilleditemPickedUp,等。

在内部,Level需要一些注意事项:

  • 跟踪已发生事件的状态。这样,它可以区分第一个被杀死的敌人和其他敌人,并且知道您是第一次捡起给定的物品。
  • LevelRequirement对象列表,描述该级别所需的特定目标集。

输入关卡时,您将创建一个Level带有LevelRequirements的a,设置游戏代码,并将其指定给该关卡。

每次发生游戏事件时,游戏玩法会将其传递给Level。依次计算汇总数据(被杀死的敌人总数,被杀死的这类敌人的总数,等等)。然后遍历其需求对象,为每个对象提供聚集数据。需求测试以查看是否满足要求,如果满足,则产生任何适当的结果行为(显示教程文本等)。

LevelRequirement 基本上需要两件事:

  1. 用来描述是否满足要求的测试描述。如果您的语言使此操作变得简单,那么这可能只是一个功能,否则您可以在数据中对其进行建模。(即有一个RequirementType类似这样的东西的枚举,FIRST_KILL然后一个大的switch知道如何检查每种东西。)
  2. 满足要求时执行的动作。

仍然存在这些要求集在何处描述的问题。您可以执行类似XML或其他文本文件格式的操作。这在以下情况下很有用:

  1. 非程序员将是创作级别。
  2. 您希望能够在不重新编译和/或重新启动的情况下更改需求。

如果都不是,我可能会直接在代码中构造它们。越简单越好。


前三点非常详细地描述了我现在使用的方法,令人印象深刻!是的,我最努力的事情是在哪里描述需求,以及如何将其转化为游戏(因为这很可能是外部因素)。感谢您的深入解释:)
omgnoseat 2011年

5

我以为您需要知道如何制作这些事件,而其余内容就是关于这些事件的。如果您只想存储这些事件,则可以使用一些关系数据库或通过文本描述它们并使用脚本语言(他将进行解析和评估)您)。:)

您想要的是识别发生的事件(1),然后执行这些事件所需的一些操作(打印消息,检查按键是否...)(2)。您还希望使这些事件仅发生一次(3)。

基本上,您想检查条件,然后安排一些行为。

如何识别事件(1)

  • 您想识别诸如“遇到的第一个敌人”,“获得新物品”之类的事件
  • 如果发生通用部分,则“ 遇到敌人 ”,“ 获得项目 ”您检查特定部分“ 第一 ...”,“ 获得项目”

什么是事件构成

从更一般的角度来看,每个此类事件均由以下组成:

  • 前提条件,您检查一下
  • 动作时的前提条件得到满足,这将做(说“”你slained先敌!“‘按A和B按钮,使连击”说’,说‘按‘确认’继续’,需要密钥‘输入’)

如何存储这些事件

在某些数据结构中:

  • 有前提条件列表(如果使用某种高级语言编写,则为字符串或代码)
  • 具有操作列表(它们可能是字符串,Quake引擎将字符串用于事件)

您也可以将其存储在关系数据库中,尽管看起来好像没有必要,但是如果您想制作一个大型游戏,则可能需要制作一个。

然后,您必须解析这些字符串/事物。或者,您可以使用某些脚本语言(如Python或LUA)或语言(如LISP),它们都可以为您解析并执行它。:)

如何在游戏循环中使用这些事件(2)

您将需要以下两个数据结构:

  • 事件队列(将要运行的事件放在此处)
  • 动作队列(计划的动作,事件表示已完成的动作)

算法:

  • 如果您认识到满足事件的某些先决条件,则将其放入事件队列
  • (3)然后,如果需要,您应该确保仅发生一次此事件:)(例如,使用布尔数组has_this_event_happened [“遇到的第一个敌人”])
  • (如果操作队列为空,则)如果事件队列中有事件,则将其操作放入操作队列并将其从事件队列中删除
  • 如果操作队列中操作,则开始执行其要求的操作
  • 如果这样的动作完成后,你从中删除动作队列

如何自己做这些动作(2)

创建具有功能“更新”的对象列表。它们有时被称为实体(在Quake引擎中)或角色(在Unreal引擎中)。

  1. 当要求它们在操作队列中启动时,可以启动这些对象。
  2. 这些对象可以用于其他用途,例如其他计时器。在《雷神之锤》中,这些实体用于整个游戏逻辑,我建议您阅读一些有关它的材料

动作“说些什么”

  1. 您在屏幕上打印一些东西
  2. 您希望此消息出现几秒钟
  3. 在“更新”中:
    • 制作变量remove_me_after,并减少经过的时间
    • 当变量为0时,请从操作队列中删除此操作
    • 您还可以删除该对象(或计划将其删除...)

动作“需要密钥”

  1. 它取决于您要如何实现,但我认为您是您要传达的信息
  2. 在“更新”中:
    • 您只需要检查想要的按键事件
    • 您可能需要一些数组/队列来保存按键事件
    • 然后您可以将其从操作队列中删除并删除对象

学习什么方法


-1正确,否则他只是调用一个函数,认真地,OP只是在满足特定条件时想要一个消息框
Maik Semder 2011年

那是一个很好的文章,但不完全是我想要的。我确实很难解释我想要什么。我添加了第二个解释:我遇到的问题是要以总是几乎相同的过程在游戏中添加一些额外的动作。就像RPG战斗一样,每个人都有转弯,选择技巧等-总是一样。但是,如果在某些情况下我会在两者之间的某个地方显示过场动画,该怎么办?修改整个游戏的结构,使其在包含过场动画的情况下进入经过改变的战斗类别,似乎效率很低。我想知道这通常是怎么做的?
omgnoseat
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.