Skip to content

python编写的回合制挂机战斗系统,支持大量复杂的技能的结算

Notifications You must be signed in to change notification settings

RShock/xiaor_battle_system

Repository files navigation

小r战斗系统

一个支持非常多种技能的回合制自动战斗系统,适合场景:挂机游戏

通过简单的编写就可以添加新的技能,如果格式足够标准,这个技能会自然的与其他技能进行化学反应 而不需要作者投入时间去处理各个技能之间的联动

战斗系统的原理

buff

buff是什么?我们最常见听说的buff是攻击力+xx% 生命恢复+xx%等等。也有人听过debuff的概念。 这里我们扩展BUFF的概念,将所有东西全部视为buff。除了上面提到的,角色的所有技能也全部以buff 形式附加在角色身上

为什么这么做?

在一些复杂游戏中,经常会出现角色玩到一半出现新技能的情况(比如大乔一开大,你就可以点击她的传送按钮)。 与其将这些技能特殊处理,不如将所有的技能都视为是后天获得的,统一管理。

buff是本系统的第一公民。

抽离buff的共性

我们注意到所有buff都可以抽象成同一种结构:

如果 A 则 B。

这里前一个A是触发条件(也可以叫trigger 触发时点 时点,反正都是我自己起的名字),它会因为特定事件而触发。后一个是动作,这是一个非常大的抽象。因为它可以模拟所有游戏规则。足以容纳游戏巨大的复杂度。 具体的说,这是为《炉石传说》《游戏王》等极端复杂游戏设计的系统,包容普通的游戏结算算是绰绰有余的了。

例子1

下面我们以一个例子示范:

小明(基础攻击100)有2个buff:

  • 攻击力+100
  • 攻击力+100%

现在需要计算小明的攻击力,这个步骤可以在buff附加好的一瞬间就主动去进行以便后续计算,也可以在需要时再计算(懒加载),这就决定了2种不同的触发时点,这里以简单的第二种作为例子:

  1. 要计算攻击力了,发送计算攻击力数据包,里面记录了小明的基础攻击100,要计算攻击力的人小明
  2. buff1触发条件:如果要计算攻击力,且计算攻击力的人是小明(或者说,计算攻击力的人是本buff的拥有者),则数据包内的攻击+100
  3. buff2触发条件,同上,数据包内的攻击力x2

随着2个buff正确响应,最后数据包内的攻击力变成了400,取出即可。

例子1深入思考

我们这里默许了小明计算攻击力时,是先加后乘,但是不同游戏攻击力计算公式有别。如果先乘后加,最后结果就是300

有的游戏非常疯狂:随着buff施加顺序的不同,结果也不同,如果变更buff顺序就会影响结果。

或者游戏默认规律就是先加后乘。这样收益是最大化的,很多游戏都这么干。

无论如何,这两个buff的触发时点是相同的,为了正确确定他们的顺序,需要一个优先级机制协调一下。

对于一些更加复杂的情况,可以强行将它们分为2个时点分别进行。

究竟何时应该计算小明的攻击力?如果一个游戏攻击力会频繁的被调用,但是修改的频率稍低,最好的选择是使用一个缓存处理。只在需要的时候刷新。

在本系统中有一个暴怒技能,玩家血量越低,攻击力越高。这使得很难决定何时才应该刷新攻击力。(只要生命变动就得改)

讨论性能问题为时尚早。所以我没写缓存。也就不需要考虑上面的复杂问题了。

例子2

第一个例子只是正常Buff的结算而已。第二个例子会讲解技能是如何成为buff的。

其实别无二致,只需要一个施加技能触发的事件即可。施加技能在一般游戏里可能是玩家按下了按钮,在挂机游戏里当然是由一个死循环反复触发的。

如果 施加技能开始技能结算 然后开始技能结算里又开始调用获取攻击力``获取防御力等等例子1里提过的很乏味的内容了 普攻也是一种技能。

其他细节

  • 可堆叠层数,且最大层数有限的buff,是需要考虑合并操作的。
  • 有些buff会使你免疫另一些buff。
  • 有些buff有持续时间
  • 有些buff会往全局变量里写东西
  • 有些buff会扭曲其他buff的效果

看起来只是小细节实际上每个处理起来都很麻烦。因为buff的行为只是一个封装好的函数而已, 除非去修改字节码,函数流程已经固定了,自然承受不起合并甚至扭曲的摧残,只能写一些很丑的代码放一些全局变量之类的打好补丁。

实现细节

msgManager.py是负责管理buff的地方,它负责让所有buff都在合适的时机运行。

这是个美差,因为buff已经自带了判断函数。

他要做的就是在受到消息时依次问每个buff要不要行动就行了。

这个模式可以认为是观察者模式或者分发生产模式或者别的什么。我不熟悉。

数据包也是个重点,例子1里提到了计算攻击力数据包,实际上事件非常多样,所以真正的数据包种类繁多。

但是完全没必要写几百个数据包类,全部塞在一个里面(msgPack.py)才是最好的。

特殊适配的部分

我针对即将做的游戏进行了特殊适配,失去了一些一般性。不过可以比较轻松的调整。

目前把所有技能作为词条附着在角色身上

没有魔力,基本没有主动技能

没有日志系统

战斗示例

skilltest.py里有很多战斗测试,运行查看log即可

完整设计

如果对本系统是如何作用于炉石等游戏的感兴趣,可阅读https://zhuanlan.zhihu.com/p/534675937

About

python编写的回合制挂机战斗系统,支持大量复杂的技能的结算

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages