• 如何高效设计游戏——从抽奖模型到圆桌算法(下)附VBA教程&战斗模拟器


    前言

        这一章节主要利用上文中引入的转盘算法来讲解说明多攻击模式战斗的应用以及圆桌理论。文章中为了进一步具象讲解,所以引入VBA实例,顺带一下VBA战斗模拟器教程。但是使用VBA战斗模拟器来设计游戏显然与“高效设计游戏”相悖,有那时间做一个无用的玩具,还不如多花点时间在该去思量的地方。请给位游戏设计者酌量。

    由于之前很多大婶们喷小的话有点罗嗦,两三句话的事情写了整篇文章,所以此回没敢放得开,好多东西尽量缩短,请大婶们见谅哈。还有一些大婶文章都不看上来就喷的,小的有句话:“请看完文章有依据之后再喷,要不然喷出来的料太骚气。如果想显得各位大婶能耐,找错对象了,小的只是一心想改善业内气氛的一介草民。”

    最后,请各位抱着正常的心态阅读此文章。改善我们业内气氛,人人有责,请不要让业内继续乌烟瘴气。

     

    抽奖模型在战斗系统中的应用

        抽奖模型在战斗系统中的应有有两种类型,第一种是回合制自动战斗类型,如类《Q将三国》游戏;另一种是多攻击形式的类型,这一类型没有限制是否是回合制,比如类《魔兽世界》游戏。下面我们将分情况讨论。

     

    自动战斗系统模型中的转盘

        随着现在网页游戏以及手机游戏的盛行,更多的战斗系统被设定成自动战斗模式,因为这类游戏正需要简化其战斗玩法,从而达到休闲娱乐的目的。自动战斗的系统需要的是多攻击模式的触发逻辑,以《Q将三国》为例,如果按照传统的设计思路会是以下情形:

        P1攻击P2

        发生在P1身上的模式有三种:A.P1的普通攻击  B.P1的暴击  C.P1的技能攻击,从中抽取一行为进行攻击。

    紧接着再判断发生在P2身上的承受模式:a.P2的闪避  b.P2的格挡  c.P2的反击  d.P2的反制,从中抽取一行为,进行回应。

        这样无疑会为我们的设计工作带来困难,一是每次战斗需要进行超过2层的逻辑判断,二是很难将“闪避”“格挡”“反击”“反制”这么多元素进行控制,从而抽奖。三是不能应变“技能攻击不可闪避”等这样的需求,如果强行制作,还需要再加一层逻辑。

        所以我们不妨看看另一种方案:

        P1攻击P2

        我们只对这几个元素进行抽奖:A.P1的普通攻击  B.P1的暴击  C.P1的技能攻击  D.P2的闪避  E.P2的格挡  F.P2的反击  G.P2的反制。

        将这次的抽奖结果作为本次攻击的“模式”,无论抽中的是对P1有益的攻击形式还是对P2有益的攻击形式。

        如此一来,我们就迎合了之前所提出的需求“技能攻击不可闪避”,并且这一方案具有以下特点:

      个项目之间是相互影响的,如果一方概率的增加会降低其他项目的概率。这特点比较适合战斗系统的要求,例如对方的闪避以及格挡的提升必然会带来我方攻击无效率的增加,但并不会让你永远攻击无效化。

      如果将敌我的所有攻击模式进行带有优先级的排列,然后再将抽奖空间强制设定一个常量,则这种系统就会转变为“圆桌算法”。(后文进行讲解)

     

    VBA中的示例应用

        下面我们就之前所讲的概念,在Excel中用VBA进行实例化,来实现我们所需要的功能。一个《Q将三国》类模拟器。

        但在哪之前,我们需要先开启Excel的一些功能:

      Excel选项→常用→在功能区显示“开发工具”选项卡

    如何高效设计游戏鈥斺敶映榻蹦P偷皆沧浪惴ǎㄏ拢└絍BA教程&战斗模拟器

      Excel选项→信任中心→信任中心设置→宏设置→启用所有宏 & 信任对VBA工程对象模型的访问

    如何高效设计游戏鈥斺敶映榻蹦P偷皆沧浪惴ǎㄏ拢└絍BA教程&战斗模拟器

        这样我们就可以进行VBA工程的编写了。

        首先在表单中设计这样一个界面:

    如何高效设计游戏鈥斺敶映榻蹦P偷皆沧浪惴ǎㄏ拢└絍BA教程&战斗模拟器

        图中各一级属性和二级属性都是我们要在接下来的程序中直接取用的,这样的设计师为了方便用户进行交互,一个简洁直观的交互方式。至于一级属性和二级属性的转化关系,由各位设计者自己设计。

        接下来我们需要构建一些方法,就以P1攻击P2为例:

        首先我们先对这几种攻击模式进行抽奖,抽奖的内容有P1的普通攻击、P1的暴击、P1的技能攻击、P2的闪避、P2的格挡、P2的反击、P2的反制。

     

    Private Sub P1HitP2()              '★★★★★★★★★P1攻击P2的方法

    Randomize

    '=======================转盘算法抽奖=======================

        Select Case Rnd * (blkTwo + dgeTwo + ctrTwo + ctaTwo + crtOne + 0.5)

            Case 0 To blkTwo

                atkMode = "Block"

            Case blkTwo To blkTwo + dgeTwo

                atkMode = "Dodge"

            Case blkTwo + dgeTwo To blkTwo + dgeTwo + ctrTwo

                atkMode = "Counter"

            Case blkTwo + dgeTwo + ctrTwo To blkTwo + dgeTwo + ctrTwo + ctaTwo

                atkMode = "Counter Attack"

            Case blkTwo + dgeTwo + ctrTwo + ctaTwo To blkTwo + dgeTwo + ctrTwo + ctaTwo + crtOne

                atkMode = "Critical Attack"

            Case blkTwo + dgeTwo + ctrTwo + ctaTwo + crtOne To blkTwo + dgeTwo + ctrTwo + ctaTwo + crtOne + 0.5

                atkMode = "Normal Attack"

        End Select

    '=======================转盘算法抽奖=======================

        其中blkTwoP2的格挡、dgeTwoP2的闪避、ctrTwoP2的反制、ctaTwoP2的反击、crtOneP1的暴击、其中强制设定P1的普通攻击为常量0.5。(为了方便起见,P1的技能攻击暂不考虑进去,但方法雷同)

        接下来我们就需要根据上一步的抽奖结果atkMode,执行相应的操作了。

     

    '================针对相应的攻击模式进行计算================

        Select Case atkMode

            Case "Block"

                dmgResult = Int((atkOne - defTwo) * (0.8 + 0.4 * Rnd) * 0.5)  '■公式修改处■

                If dmgResult < 1 Then dmgResult = 1

                beHitedDmg = 0

                battleReport = "P1发动攻击,【格挡】P2受到" & dmgResult & "点伤害!" & Chr(10)

            Case "Dodge"

                dmgResult = 0

                beHitedDmg = 0

                battleReport = "P1发动攻击,【闪避】P2受到0点伤害!" & Chr(10)

            Case "Counter"

                dmgResult = 0

                beHitedDmg = Int((atkTwo - defOne) * (0.8 + 0.4 * Rnd))       '■公式修改处■

                If beHitedDmg < 1 Then beHitedDmg = 1

                battleReport = "P1发动攻击,【反制】P1的攻击被反制,P1受到" & beHitedDmg & "点伤害!" & Chr(10)

            Case "Counter Attack"

                dmgResult = Int((atkOne - defTwo) * (0.8 + 0.4 * Rnd))        '■公式修改处■

                If dmgResult < 1 Then dmgResult = 1

                beHitedDmg = Int((atkTwo - defOne) * (0.8 + 0.4 * Rnd))       '■公式修改处■

                If beHitedDmg < 1 Then beHitedDmg = 1

                battleReport = "P1发动攻击,【反击】P2受到" & dmgResult & "点攻击,P1被反击受到" & beHitedDmg & "点伤害!" & Chr(10)

            Case "Critical Attack"

                dmgResult = Int((atkOne - defTwo) * (0.8 + 0.4 * Rnd) * 1.6)  '■公式修改处■

                If dmgResult < 1 Then dmgResult = 1

                beHitedDmg = 0

                battleReport = "P1发动攻击,【暴击】P2受到" & dmgResult & "点伤害!" & Chr(10)

            Case "Normal Attack"

                dmgResult = Int((atkOne - defTwo) * (0.8 + 0.4 * Rnd))   '■公式修改处■

                beHitedDmg = 0

                battleReport = "P1发动攻击,【攻击】P2受到" & dmgResult & "点伤害!" & Chr(10)

            End Select

    '===================针对相应的攻击模式进行计算=================

                  

    End Sub

     

        主要的方法已经写好了,剩下的只需要在各个攻击行为中调用该方法,然后取用相应的dmgResultbeHitedDmg以及battleReport就可以了。

        详情请看本文末尾所带的附件。

     

    圆桌算法的应用

        上会大概已经介绍过了,圆桌算法有两个必要条件:①对抽奖内容进行优先级排列;②强制限定抽奖空间。

    对于圆桌算法,还有一个比较形象的解释:“在一个面积固定的圆桌上摆放东西,如果圆桌上摆放的物品已经满了,那么其他优先级低的物品将无法继续摆放到圆桌上,而优先级高的物品将会把圆桌上优先级低得物品挤出圆桌。”

    这种设定会使得游戏拥有相当丰富的可玩性,只要你肯花心思去设计。例如在《魔兽世界》中Boss的碾压攻击具有超强的伤害力,但是我们又会有一种Tank职业来做肉盾免于这种碾压攻击,正是因为这种职业的免伤被动技能会将碾压攻击挤出圆桌。

    我们还是回到实例上。

    上面的系统我们稍作修改。首先我们先把设定一个优先级,从高到低有:“闪避”、“格挡”、“暴击”、“反制”、“普通攻击”。原则是要把对“被攻击方”有益技能的优先级设定为高,但也可以结合自己想要的特点来设定。接下来就是要限定抽奖空间,暂定为1。这样一个圆桌抽奖已经完成了。

    借用我们之前编写过的代码我们进行稍作修改:

    Randomize

    '=======================转盘算法抽奖=======================

        Select Case Rnd                                  注意变化,限定抽奖空间为1

            Case 0 To dgeTwo                            ‘注意优先级,闪避

                atkMode = "Dodge"

            Case dgeTwo To dgeTwo + blkTwo                ‘注意优先级,格挡

                atkMode = "Block"

            Case dgeTwo + blkTwo To dgeTwo + blkTwo + ctaTwo   ‘注意优先级,反击

                atkMode = "Counter Attack"

            Case dgeTwo + blkTwo + ctaTwo To dgeTwo + blkTwo + ctaTwo + crtOne   暴击

                atkMode = "Critical Attack"

            Case dgeTwo + blkTwo + ctaTwo + crtOne To dgeTwo + blkTwo + ctaTwo + crtOne + ctrTwo   注意优先级,反制

                atkMode = "Counter"

            Case Else                          ‘注意优先级,普通攻击

                atkMode = "Normal Attack"

        End Select

    '=======================转盘算法抽奖=======================

     

        之后的内容相似。

        我们来看一下如此设计的效果。看以下例子:

    项目

    概率

    P1暴击

    0.1

    P2闪避

    0.15

    P2格挡

    0.1

    P2反制

    0.1

    P2反击

    0.15

     

     

     

     

     

     

        所有项目的概率和为0.6,那么还有0.4作为普通攻击的触发概率。但是这期间如果其他项目的触发概率的增加会减少普通攻击的触发概率,直至把普通攻击完全挤出去,甚至会把优先级次低的“反制”慢慢的挤出去。如:

     

    项目

    概率

    P1暴击

    0.2

    P2闪避

    0.35

    P2格挡

    0.25

    P2反制

    0.1

    P2反击

    0.15

     

     

     

     

     

        由于其他优先级高的四项的概率加和已经等于0.95,所以次级的反制只有0.05的可用生效范围。以此类推,直至最高级的“闪避”会把所有攻击模式全部挤出圆桌,以至于每次攻击只能被闪避。

     

        至此,本章结束。

        游戏中还有好多抽奖模型的存在,我们游戏设计者需要透过现象看本质,找出其内在联系,万变不离其中,形成一套自己的设计思路,这才是作者写文章的目的。

        本文仅供参考,请尊重个人劳动成果。如有一腔热血请不要发泄此处,各位大婶们可以选择继续造福人类。

  • 相关阅读:
    TCP重传
    GIT常用命令参考图
    nodepad++ 快捷键加常用操作
    Django学习之manage.py使用
    Python遍历目录
    Pycharm 2017 12月最新激活码
    Python 基础之列表去重的几种玩法
    ddos cc攻击简单介绍(转)
    linux升级python版本至3
    linux解压xxx.tar.xz文件
  • 原文地址:https://www.cnblogs.com/youlechang123/p/2724962.html
Copyright © 2020-2023  润新知