Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

技能事件系统 #25

Open
coneo opened this issue Nov 1, 2016 · 0 comments
Open

技能事件系统 #25

coneo opened this issue Nov 1, 2016 · 0 comments
Labels

Comments

@coneo
Copy link
Owner

coneo commented Nov 1, 2016

技能回调

在攻击命中对方时,如果对方有状态A,则给自己回血,并清除对方的状态A

这样的技能流程,我们单单依靠正常的技能流程很难实现。需要在技能流程中做一些特别的处理,在命中的时候,做一个回调,该回调对状态进行检测,并做一些操作。假设需求有变,“在攻击命中对方时,检测自己对方有被动技能B,则给对方造成一次额外的伤害”。我们就需要一定的机制来支持这种变动。

考虑对以上需求作一个分解:

攻击命中对方 —— 事件
对方有状态A —— 条件
给自己回血 —— 动作
清除对方状态A —— 动作

因此,上面的需求可以抽象为:当触发事件时,作一些条件检测,当检测通过,则执行一些动作。

我们称这个抽象机制为:技能事件系统

有了该事件系统,我们不仅可以实现以上类似的需求,还能扩展应用到其他情况,比如击杀对方时处理,受到伤害时处理等等。

上面的需求用xml表示如下:

<event type="attack_other">
     <conditions>
          <condition hasstate="xxx"/>
     </conditions>
     <actions>
          <action changehp="xxx"/>
          <action clearbuf="xxx"/>
     </actions>
</event>

实现机制

实现起来很简单,我们把该机制实现为全局无状态的。全局意味着只有一份事件管理实例,通过传参的方式来实现不同的处理。无状态意味着每个action和condition不会存储和具体事件相关的数据,他们的职责就是根据一些参数或者外部数据进行对应的处理。

为了便于扩展,我们用多态的方式来实现,定义一个actionbase和conditionbase基类,分别定义一个纯虚函数do和check用于子类实现。

在子类中,只需继承对应的基类并实现纯虚函数即可。

每个事件由多个condition和action组合而成,结构如下:

event {
  condition list
  action list
}

当一个事件触发时,分别检测condition list,如果所有条件都满足,再分别执行action list。

最终我们通过如下的统一接口来触发一个事件,并交给事件系统处理。

skilleventmgr.trigger(eventtype,me,other)

这里eventtype表示事件类型,me表示事件主实体,即一个player实例,那么other是什么鬼。我们通常的技能事件都涉及两个实体,比如A攻击了B,A被B杀了等等。发现这种需求特别多,就做到机制里去了,当然了,你可以通过黑板等数据管理方式把other传进来。

黑板机制

我们把事件系统中的数据分为两块,其一是配置数据,通过配置文件配置,跟具体的condition和action绑定在一起,这些数据作为具体condition和action的数据成员存下来。比如:

<checkhplow  hp=“50”>

这里hp数据是作为数据成员存在checkhplow这个condition里的。

其二,我们还需要一些外部数据供事件系统使用,比如player的当前血量,比如这次攻击的伤害量。当前血量可以通过player的接口直接获取,那伤害量我们没必要存在player里吧。那这种数据该如何传递到事件系统里呢?这时候就引出黑板机制了。

对于这类数据,我们需要的是一块数据集来表示。在触发事件的时候赋值,供事件系统访问,但只能是只读,整个事件执行完后,清空即可。我们把这块数据集称之为黑板(black board)。该黑板承担的责任就是数据的集合,实际的修改和重置都是外部控制的。由于我们的事件系统是全局的,因此我们只需一块黑板足矣,用完即走。

通过上面的实现步骤,我们可以搭建出一个完整的技能事件系统了

@coneo coneo added the server label Nov 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant