我会为事件处理程序疯狂吗?我的设计是否走错了路?


12

我想我已经决定我真的很喜欢事件处理程序。我可能会因分析瘫痪而受苦,但是我担心会使我的设计变得笨拙,或者在我的设计决策中遇到其他无法预料的后果。

我的游戏引擎目前使用平移式高架摄像机进行基本的基于Sprite的渲染。我的设计看起来像这样:

场景处理程序

包含实现SceneListener接口的类的列表(当前仅限于Sprites)。每个刻度调用一次render(),并发送onCameraUpdate(); 消息发送给SceneListeners。

InputHandler

每个刻度轮询一次输入,然后将简单的“ onKeyPressed”消息发送给InputListeners。我有一个Camera InputListener,它包含一个SceneHandler实例并触发updateCamera();。基于输入的事件。

AgentHandler

每个刻度一次在任何代理(AI)上调用默认操作,并将检查堆栈中是否有已注册的任何新事件,并根据需要将它们分配给特定的代理。

因此,我有一些基本的Sprite对象,它们可以在场景中移动并使用基本的转向行为进行移动。我已经开始进行碰撞检测了,这是我不确定我的设计方向是否正确的地方。拥有许多小型事件处理程序是一种好习惯吗?我想我必须要实现某种CollisionHandler。

我会更好地使用一个更统一的EntityHandler来处理一个类中的AI,碰撞更新和其他实体交互吗?还是只是实现许多不同的事件处理子系统就可以了,它们会根据事件类型将消息传递给彼此?我是否应该编写一个仅负责协调所有这些子事件处理程序的EntityHandler?

我意识到在某些情况下,例如我的InputHandler和SceneHandler,它们是非常特定的事件类型。我的游戏代码很大一部分都不关心输入,而很大一部分则不关心纯粹在场景渲染中发生的更新。因此,我感到孤立那些系统是合理的。但是,我要问的是专门针对游戏逻辑类型事件的问题。

Answers:


21

基于事件的设计主要涉及实现Reactor设计模式。

在开始设计组件之前,您应该了解这种模式的局限性(您可能会找到很多有关此信息)。

第一个也是最重要的问题是处理程序必须快速返回,因为在基于GUI的框架和基于javascript的应用程序上做过一系列工作的每个人都非常了解。

当您以相当大的复杂性开发每个应用程序时,您迟早会遇到一些处理程序,该处理程序执行需要时间的复杂工作

在这些情况下,您可以区分两种情况(不一定是互斥的):

复杂的事件相关责任和复杂的事件无关责任。

与事件相关的复杂职责:

在第一种情况下,您将太多职责合并到一个组件处理程序中:响应事件而采取的动作过多,或者例如正在运行同步。

在这种情况下,解决方案是将处理程序拆分为不同的处理程序(必要时在不同的对象中),并让一个处理程序触发事件,而不是直接调用处理程序代码。这将允许您允许在管理更高优先级的事件之前进行管理,因为在将事件添加到事件队列之后,您的主处理程序已返回。

另一种解决方案是让外部实体触发事件,并让其他实体订阅(如果您对此感兴趣,则可以选择计时事件是最简单的例子)。

与事件无关的复杂职责:

第二种情况是在事件发生后采取的行动存在内在复杂性时发生的:例如,您必须在事件发生后计算斐波那契数。

在这里,Reactor模式基本上失败了,将斐波那契生成算法拆分为小块,在终止时触发事件以触发下一步的价值很小。

这里的解决方案是将螺纹设计混合到反应堆中,好消息是,如果复杂性是内在的(因此您正在阅读正确的部分),则很有可能可以启动独立的线程来完成工作,并且几乎不需要了解其他与Reactor相关的组件。

为了处理这种情况,我发现在灵活的线程池上采用作业队列很有用

当处理程序需要启动长动作时,它将该动作封装到要放入作业队列的作业单元中。这种封装的动作需要具有触发事件到反应堆线程的手段。作业队列管理器可能会在其自己的线程中或在反应堆线程中运行并对“ newJob”事件做出反应。

作业队列管理器执行以下操作:

  • 如果缓冲池能够提供一个线程(有空闲线程或允许创建新线程),它将使用其棚式算法从弹性线程池中为线程分配作业单元

  • 侦听池本身以查看作业单元是否完成,以便可以恢复线程以执行另一个未决单元(如果有)。

使用事件触发机制,作业单元可以触发事件以通知完成情况,更新状态,警告,错误或在需要的任何时候。灵活的线程池确保了资源的充分利用,同时避免了死线程挂起整个系统;作业队列使您可以选择为不同类型的操作分配哪种优先级,因为您知道它们将需要一致量的计算资源。


3
+1非常详尽。对于好奇的读者,一些链接将是很棒的。
sam hocevar 2011年

1

在大多数情况下,使用事件而不是其他选项通常可以提高速度和分散性。我认为,如果您可以使用很多事件,那么应该去做。

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.