炉石卡牌实现机制的一点猜想
假设我们要实现一个炉石的对战机制,要怎么做呢?
并没有游戏开发经验,所以以下都是乱猜加瞎扯~
分类
首先,我们把炉石里的主要元素分成几类:
法术
法术很好理解,一般来说法术包括几个要素- 目标
- 可能是一个目标也可能是多个目标
- 可能包含一个筛选,比如「对非恶魔随从造成伤害」
- 效果
- 可能是给目标一个 buff 或者 debuff,也可能是造成伤害等等
- 大部分法术都是立即效果
- 也有一部分法术是触发效果,比如
奥秘
,比如本回合随从生命值不会降低到 1 点以下
- 目标
武器
英雄
- 英雄技能可以看作一个法术
随从
随从本身具有的属性
- 花费/攻击/血量
- 类别: 恶魔/鱼人/野兽
- 其他
我们以 https://hearthstonejson.com/ 上的卡牌火车王的 Json 数据为例:
{ "id": "EX1_116", "name": "Leeroy Jenkins", "text": "<b>Charge</b>. <b>Battlecry:</b> Summon two 1/1 Whelps for your opponent.", "rarity": "LEGENDARY", "type": "MINION", "cost": 5, "attack": 6, "health": 2, "collectible": true, "set": "EXPERT1", "faction": "ALLIANCE", "artist": "Gabe from Penny Arcade", "flavor": "At least he has Angry Chicken.", "mechanics": [ "BATTLECRY", "CHARGE" ], "dust": [ 1600, 3200, 400, 1600 ] }
随从效果
- 即上面的
mechanics
数据 - 目前炉石包括了
冲锋、亡语、发现、战吼、法术伤害、连击
等等大概二十多种效果
- 即上面的
效果
- 法术效果
- 法术效果相对来说容易归纳
- 随从效果
- 实际上随从效果可以认为是法术效果,比如自带亡语的随从,可以认为是通过法术给予了亡语效果——毕竟,炉石里面确实存在着这样的法术
- 具有亡语效果
随机召唤一个法力消耗为 3 的随从
的随从死亡时,可以认为是使用了一个随机召唤一个法力消耗为 3 的随从
的法术 - 光环是一种特殊的法术效果,拥有更加复杂的触发条件,比如
将你的治疗法术或技能改为造成等量的伤害
对局
- 从对局中我们可以总结出一些规则,比如大家经常会讨论的
结算顺序
- 虽然打出一张牌表面上看起来很简单,但是背后其实包括了多个阶段,比如:
- 选择战吼目标并出牌,此时扣费
- 登场效果触发,这个时候一部分其他卡牌的效果已经会被触发,比如
任务达人
- 召唤效果触发,比如会触发
送葬者
- 战吼效果触发,此时开始结算战吼效果
- 奥秘效果触发,这也是为什么
谢娜
这张牌可以先偷到复制但是自己本身并不会被复制 - 召唤结束,这时会触发
飞刀杂耍者
之类的效果
(结算比较复杂,而且涉及到各种死亡结算和效果,而且暴雪也没有出官方的结算规则,所以,以上只是举个栗子~
- 虽然打出一张牌表面上看起来很简单,但是背后其实包括了多个阶段,比如:
- 从上面的例子可以看到,不同的牌在不同的阶段触发效果
假设我们需要实现一张飞刀杂耍者
,每召唤一个随从就发射一把飞刀- 我们可以很容易分开两个角色
- 系统,它担任裁判的角色
- 卡牌
这样由系统去执行整个流程,在召唤了一个随从后,通知飞刀杂耍者
去执行发射飞刀的任务
- 我们可以很容易分开两个角色
- 显然我们没办法把所有卡牌逻辑都塞在
系统
这个角色中,假设我们有 500 张卡牌,那么系统
这部分的调用代码可能会突破天际 - 我们也不能让
飞刀杂耍者
自己去监控整场对局,从而决定什么时候发射飞刀,显然这样系统
这个角色就失去了其意义,代码也会无比混乱 - 实际上对于这样的问题,我们有一个经典的例子(或许你在面试中已经被问了无数次的 「猫叫老鼠跑人醒」)
- 这就是观察者模式(事件-通知)
- 我们只需要让
飞刀杂耍者
在系统
那里注册一个事件,告诉它,有随从被召唤的时候,通知我,然后由我来执行对应的逻辑 系统
则需要维护一个注册的事件列表,比如随从被召唤的事件、随从死亡的事件等等系统
按结算规则来执行,并在对应的事件触发的时候,按一定的顺序去通知即可
其他
- 炉石包含很多不同的效果,事实上这也正是它好玩的地方,但一来暴雪没有出明确的结算规则和效果解释,有些卡牌的效果也找不到同类和规律(比如改变战吼效果的
铜须
光环,和改变法术执行目标的扰咒术
等等),所以有些时候想总结一套规则来套用所有卡牌不太容易 - 对于单个的特殊的效果,hardcode 也是一个解决办法
插件
额外插一点关于炉石插件的内容,之前看到有童鞋在好奇
- 炉石传说有一个隐藏的 debug-logging 模式,打开之后会产生非常详细的记录,通过解析这个 log 可以做到记录和获取对局信息
- 网易的盒子貌似额外使用了抓包解析的方法,所以功能会强大一些,比如导入导出卡组的功能
- 但是考虑到可能触犯 ToS ,其他插件没有这么做
- log 大概是这样的:
[Zone] ZoneChangeList.ProcessChanges() - id=1 local=False [name=Garrosh Hellscream id=4 zone=PLAY zonePos=0 cardId=HERO_01 player=1] zone from -> FRIENDLY PLAY (Hero)
- 可以看出 log 是非常详细的,包含各种事件的触发
- 解析完整的 log 可以帮助理解整个炉石的事件机制
- 当初想要自己实现盒子的时候参考过这篇文章 https://www.reddit.com/r/hearthstone/comments/268fkk/simple_hearthstone_logging_see_your_complete_play
- 当然现在很多开源的插件了,比如 https://github.com/HearthSim/Hearthstone-Deck-Tracker
待补充
想到哪写到哪,有什么想法再补充吧 =-=