V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
franklinre
V2EX  ›  问与答

卡牌游戏的后端代码是如何设计的?

  •  
  •   franklinre · 328 天前 · 4265 次点击
    这是一个创建于 328 天前的主题,其中的信息可能已经有所发展或是发生改变。
    像炉石传说这种游戏,各种战哄类,光环类卡牌,种类很多,组合很多,感觉有无限种组合。
    例如:打出一张卡牌可以给全员+2 攻击力。
    有些卡牌可以让这个效果触发两次,有些卡牌可以让这个效果*2 ,有些卡牌攻击力增长时会加血。。等等。随着游戏更新,还可以出现其他更多效果。
    应该不是用 if else 写出来的吧。是怎么实现的呢?
    34 条回复    2023-05-27 03:56:10 +08:00
    fordoo
        1
    fordoo  
       328 天前
    =各种角色属性+技能公式+配置表
    clecho
        2
    clecho  
       328 天前
    op 想自己实现一个炉石吗? cool
    InkStone
        3
    InkStone  
       328 天前
    我自己设想的话,大概是把整个回合精确划分为多个阶段,每个动作(比如攻击)也划分为多个子阶段,然后各种修改效果都通过在这些阶段上插入回调链来实现
    clecho
        4
    clecho  
       328 天前
    我的想法是,每张卡牌的血量费用等作为类的基础属性,战吼、亡语等作为 interface 分别给每一类效果做方法,这样一个对象就能有多个复合效果了,但是结算顺序我还没想过
    andyskaura
        5
    andyskaura  
       328 天前
    你举得例子都是数值策划的工作,由他们维护角色特性,技能数值,使用效果。
    wxw752
        6
    wxw752  
       328 天前
    那些 buff 的属性肯定是分了很多种类型,然后就像配置优惠券一样,各种叠加就可以了。

    不同品类的优惠券能不能叠加、谁先谁后需要看配置。感觉和优惠券唯一的区别是优惠券是减,计算 buff 加成是加减都有。
    gam2046
        7
    gam2046  
       328 天前
    以前玩三国杀的时候,考虑过。要是我的话,基本思路和#3 差不多。

    先将整个游戏拆分成若干个独立的阶段,例如
    洗牌、发牌、(发牌前)判定、准备、行动、结束、(结束后)判定、行动外回合等等

    在每个阶段可以只完成自己的事情,比如某些 dot 的持续回合数增减,人员状态的设置等等,可能会相对简单一些。

    同时为了扩展日后可能存在新的机制,采用调用链的方式,向各个独立阶段中插入自己的业务逻辑。
    LandCruiser
        8
    LandCruiser  
       328 天前
    我猜是这样的,特定的卡牌是对象,分别隶属于增减益类,攻击类,召唤类等等。 回合内的行为是个队列。增减溢类方法执行,攻击方法执行等等。每个类都有哪些卡牌,这个是策划定的,有个工具,可以让策划制作卡牌导入游戏进行测试
    cxtrinityy
        9
    cxtrinityy  
       328 天前 via Android
    我觉得最具有参考意义的是万智牌,因为万智牌本身的阶段区分,各阶段允许操作,结算顺序都很清晰,这样实体和客户端就可以互相借鉴。
    sunny352787
        10
    sunny352787  
       328 天前
    你是要策划的设计还是程序的实现?

    策划部分就是设计很多基础效果然后想办法组合
    程序就是读 Excel+有限状态机
    WashFreshFresh
        11
    WashFreshFresh  
       328 天前
    确实,有限状态机非常合适,就是会越来越复杂。
    polo3584
        12
    polo3584  
       328 天前
    数值配表,每个属性还有各种逻辑优先度,最后一个公式算出来
    timelessland
        13
    timelessland  
       328 天前
    @gam2046 我几年前做的卡牌(战棋)类游戏确实是这样设计的,回合制情况下,每一回合分为若干阶段。
    每一张战场上的牌是一个单位,单位挂着各类技能,技能的构成:触发阶段,触发条件,效果;阶段内,条件满足,则触发效果;
    人机对战,对面是 AI 的话,会有额外的计算方式,左右触发条件。
    franklinre
        14
    franklinre  
    OP
       328 天前
    @clecho 不是想自己实现一个炉石。就是感觉有无限种可能,想在 java 开发时借鉴一下。
    akiyamamio
        15
    akiyamamio  
       328 天前
    我更好奇的是,这种卡牌客户端和服务器怎么同步的?
    之前看过几个录像,感觉炉石酒馆战旗是不同步的,各算各的,有时候你看到是自己赢了,结束后看战绩发现是自己输了
    guoyongqiang
        16
    guoyongqiang  
       328 天前
    可以反编译下杀戮尖塔看看
    lifeintools
        17
    lifeintools  
       328 天前
    在像炉石传说这样的卡牌游戏中,实现各种不同效果和组合通常需要更复杂的逻辑和数据结构。使用大量的 if-else 语句可能不是最好的解决方案,因为这样的代码会变得冗长、难以维护和扩展。

    在实现卡牌效果和组合的过程中,常用的方法是使用面向对象编程( Object-Oriented Programming )的概念。游戏中的每个卡牌可以看作是一个对象,具有属性和方法。这样可以通过定义卡牌类( Card Class )和效果类( Effect Class )来管理不同的卡牌和它们的效果。
    xianyv
        18
    xianyv  
       328 天前
    都是效果类支撑的, 将相同效果抽取成效果类, 使用的时候,调用不同效果类就可以了, 具体的数据都做成可配置的, 通过配置,将不同卡牌进行数值上的区分.
    xianyv
        19
    xianyv  
       328 天前
    @akiyamamio 感觉是本地计算,然后谁先算的快谁上传服务器
    sunny352787
        20
    sunny352787  
       328 天前
    @franklinre 所谓无限可能也只是各种基础效果的组合而已,比如做一个禁止行动的效果,那你客户端配合不同特效就有了冰冻、眩晕、僵直等一系列效果;再做个速度变化,100%就是标准速度,50%就是减速 200%就是加速,这就又是好多种冰水火等的增益和减益。每种效果再加个目标,是给敌人加还是给自己加,加一个人还是范围,那就区分出了治疗辅助还是伤害,还有光环等不同效果。

    卡牌本质上也都是这些东西的组合,甚至比这些更简单,ARPG 类的比较好举例而已。

    最终的代码逻辑实现基本都是状态机+读表,复杂点的行为树+读表,SB 点的 ifelse+读表,反正都是花式读表。结构上就最简单的父子继承树,最近也开始流行结构化 ECS 什么的,看个人喜好了。
    franklinre
        21
    franklinre  
    OP
       328 天前
    @sunny352787
    感觉这个靠谱。就是想了解程序设计方面。
    是一种效果就是 Excel 的一个字段,一张卡牌就是 Excel 的一条记录吧?
    如果我有一个标签系统,其中某个标签的作用是给被这个标签标记的字段在某个时间发送短信。(相当于卡牌)
    还有一个问卷系统,用户可以在某个字段标记标签,以实现标签内的功能。(相当于触发卡牌效果)
    这种该怎么用 Excel+有限状态机实现呢?
    pkoukk
        22
    pkoukk  
       328 天前
    对炉石的多年( BUG )观察
    首先,有一个场地的概念,场地相当于一个 channel ,它会向所有上场的卡牌广播场地事件,卡牌根据自己的 event handler 做出处理。
    事件类型有优先概念,例如大家都知道的亡语大于复生,同类型事件根据登场顺序触发。
    每个版本都添加的新”特效“,应该就是一个新的事件类型,根据程序或者策划安排触发的顺序。
    那么对应的,卡牌在登场的时候,会根据设定触发 channel 事件。
    理论上,是不需要什么 if else 或者状态机的,就是一个事件流系统。
    但是实际上,为了实现某些描述特别长的特效,或者连锁效果,肯定还是存在特殊处理的情况的
    这种情况,往往在以后的版本更新某些新机制的时候,组合起来产生意外的效果( BUG )
    但你要是硬去分析事件链,是讲得通的
    所以炉石流行一句话,炉石传说没有 BUG ,这都是机制
    AkashicRecords
        23
    AkashicRecords  
       328 天前
    可以看看这个: [教程资源] ygocore 卡片添加教程完整版 https://tieba.baidu.com/p/3184047731
    ygocore 是开源的游戏王线上对战平台,可以自己编写卡牌并添加
    sunny352787
        24
    sunny352787  
       328 天前
    @franklinre 不是靠谱,是我这十几年做的好多游戏都是这么做的...游戏的代码设计是比 CRUD 复杂点但也有限,状态机用的确实多一点,但大部分逻辑也都是各种继承查询啥的
    SxqSachin
        25
    SxqSachin  
       328 天前
    我目前的实践是:每个操作分为多个阶段,比方对于发起攻击这件事情,可以分为发起攻击->自身造成伤害前->对方受到伤害前->对方受到伤害后->自身造成伤害后->攻击结束等环节;打出卡牌也可以分为某张卡牌打出前(奥秘、陷阱类)->某张卡牌打出后(战吼)。游戏中的任意实体,都可以单独向每个环节中注册事件,注册的事件允许参与并调整每个阶段的数值或走向,每个环节中事件根据注册顺序来依次执行。
    sunny352787
        26
    sunny352787  
       328 天前
    @franklinre 游戏的逻辑大部分都是在内存里处理,如果是传统的 Java 各种框架的话其实不太好写状态机,不过可以做一些变化比方说把状态信息存在 Redis 然后统一处理之类的
    sunny352787
        27
    sunny352787  
       328 天前
    @franklinre 就你说的这个标签系统和问卷系统吧,我觉得你还是别在游戏这边找灵感,有现成的解决方案就不要把事情搞复杂了
    Rexxar
        28
    Rexxar  
       328 天前
    这也不是卡牌类独有的吧,光环,buff ,战吼在各种游戏里都有叠加的
    wyhooo
        29
    wyhooo  
       328 天前
    触发器+配置+状态机
    fanxasy
        30
    fanxasy  
       328 天前
    THESDZ
        31
    THESDZ  
       328 天前
    1.生命周期
    2.基于生命周期注册钩子函数,钩子运行使用命令模式(也可以是代理模式+适配器模式)
    zhouyg
        32
    zhouyg  
       328 天前
    不知道 lz 有没有玩过游戏王,这个应该够复杂了,对应上面发的 ygopro
    elonlo
        33
    elonlo  
       328 天前
    这让我想起当年做 3D 卡牌游戏战斗的时光。。。各种 buff 叠加,shader 满天飞哈哈
    dayeye2006199
        34
    dayeye2006199  
       327 天前
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3032 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:56 · PVG 22:56 · LAX 07:56 · JFK 10:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.