植物大战僵尸吧 关注:566,441贴子:5,117,696

有关僵王的一些机制(总集篇)

只看楼主收藏回复

上篇https://tieba.baidu.com/p/8888289640,并申请撤精;
中篇https://tieba.baidu.com/p/9160076451
下篇没了,直接汇总一下发总结篇,并申精。
其实还应该有个附篇,放弃了。


IP属地:江苏1楼2025-05-25 22:56回复
    2楼备用,勿回。


    IP属地:江苏2楼2025-05-25 23:09
    收起回复
      2025-09-03 15:19:40
      广告
      不感兴趣
      开通SVIP免广告


      IP属地:江苏3楼2025-05-25 23:15
      回复
        一、琐碎知识
        1.1 坐标与判定
        僵王的坐标位于(0,0),也就是左上方,属于一路。如果用ShowMe查看的话,鼠标选停在场地左上角才能读到僵王的数据。
        但是僵王防御域的横向偏移超级大。防御域偏移(700,80),大小90*430,也就是(700,80)-(790,510)的方框。
        如图(这里鼠标所指距离左上角有些偏,但内存是不错的,应该是ShowMe的机制,不知道具体ShowMe是怎么写的):

        作为参照,屋顶九列大小80*425,坐标范围是(680,70)-(719,494)。如图:


        IP属地:江苏4楼2025-05-25 23:17
        回复
          1.2 选行
          僵王属于一路,且不会记录进各行“上次和上上次被选择”的记录,即不会影响其他僵尸的选行。
          .
          1.3 存在时间
          游戏开始时僵王已存在时间为583,即此时为游戏计时0、低头倒计时5000、已存在时间583。
          .
          1.4 损伤度
          损伤度与僵王血量的关系如下,两个临界值分别是50%和80%,小于临界值则进入下一损伤度:


          IP属地:江苏5楼2025-05-25 23:18
          回复
            二、倒计时与技能的触发
            2.1 根据倒计时触发技能
            僵王一共有五个技能:放僵尸、低头(吐球)、砸车、放蹦极、跺脚。与放技能有关的倒计时有五个,本文将其分为一个闲置倒计时和四个技能倒计时:

            (这里说的闲置倒计时其实就是每个僵尸都有的那个属性倒计时)
            其中初始值为-1的那两个倒计时暂时保持不变,也就不会执行技能,等待后续激活。
            .
            倒计时的应用和重置机制如下:
            1. 只有在闲置倒计时归零时,才会进一步判断技能倒计时是否归零,若归零则执行技能。技能倒计时归零时,先保持为0等待闲置倒计时归零。
            2. 闲置倒计时归零时,若有多个技能倒计时同时归零,优先级为跺脚>放蹦极/砸车>低头>放僵尸,未启动的倒计时保持为0,等待下一轮闲置倒计时归零。
            3. 当一个技能开始时,该动作对应的倒计时重置,闲置倒计时保持为0;动作结束后,闲置倒计时重置。
            .
            砸车行为比较特殊,当车落下时(不是动作开始时)会重置所有技能倒计时,对于蹦极砸车倒计时的重置与损伤度有关,见2.4;闲置倒计时不重置,动作还没结束它就不能重置。
            .
            计算一下运气最坏的情况:某个技能倒计时减为1时闲置倒计时刚好归零并重置为200,那么技能倒计时归零后,就要额外经过-1+200=+199cs才会开始技能。


            IP属地:江苏6楼2025-05-25 23:20
            回复
              2.2 放蹦极还是砸车
              蹦极砸车倒计时归零时,判断放蹦极还是砸车的概率:冒险75%蹦极25%砸车,小游戏均为50%。
              .
              2.3 根据损伤度触发技能
              首先补充一下,具体来说每帧内的顺序是这样的:
              检查闲置倒计时是否归零
              →若为0,则根据[+12C]和损伤度,判断是否要放蹦极或砸车
              →若不需要因为损伤度放技能,则依次判定技能倒计时是否归零,且判定顺序为跺脚→放蹦极/砸车→低头→放僵尸。
              其中第二步具体是这样的:游戏开始时[+12C]为0,比较该值与当前的损伤度,若两者不同,则将当前损伤度写入[+12C],并判断损伤度是否是1,是则放蹦极并重置蹦极砸车倒计时,否则砸车并重置跺脚倒计时。
              从而实现的效果是:僵王损伤度刚达到1时放一次蹦极并解封蹦极砸车倒计时,刚达到2时砸一次车并解封跺脚倒计时。
              .
              2.4 连续砸车不低头的bug
              砸车时重置倒计时的逻辑如下:
              如果损伤点为1或2,则重置跺脚倒计时(原本损伤点为2时才解封);
              如果损伤点为2,则再重置蹦极砸车倒计时(原本损伤点为1时就会解封)。
              这就导致:
              1. 即使损伤点还没到2,如果砸过车,跺脚倒计时也会提前启动;
              2. 当损伤点为1时,蹦极砸车倒计时不会随砸车重置为6500,而是在动作开始时正常重置为4000~5000的随机数,而低头倒计时会随砸车重置为5000,因此必然出现蹦极砸车倒计时早于低头倒计时归零的情况,运气不好就有可能连续砸车而不低头。
              游戏设定蹦极砸车倒计时6500>低头倒计时5000,可能本来就是为了防止连续砸车,结果似乎是写反了,反而导致了让人两眼一黑的结果。


              IP属地:江苏7楼2025-05-25 23:21
              回复
                三、技能详述
                先补充一句不知道放哪好的话,僵王每次开始动作前,都会先取消冻结和减速状态。(减速能理解,但是冻结状态下倒计时都停了啊?)
                .
                3.1 放僵尸
                僵王先选择放僵尸的行数,选行规律与常规关卡一致。
                然后选择僵尸种类,与僵王的存在时间直接有关:
                当存在[0,3500]时,出普僵;
                当存在(3500,8000]时,出路障;
                当存在(8000,12500]时,出铁桶;
                当存在(12500,+∞)时,有以下12种僵尸可选,等概率随机:
                路、杆、桶、报、门、橄、车、丑、跳、梯、篮、巨(若为一路则不出巨人)。也就是所有可以出在屋顶的僵尸除掉普、橇、气、雪、偷。
                .
                刚出生的僵尸横坐标600。不过实际上僵尸在出现同帧就开始移动(尽管视觉上僵王的手还没松开),推测是因为正常游戏下僵王的编号是最小的0,同一帧内其他僵尸都在僵王之后更新。


                IP属地:江苏8楼2025-05-25 23:21
                回复
                  2025-09-03 15:13:40
                  广告
                  不感兴趣
                  开通SVIP免广告
                  3.2 低头、吐球
                  3.2.1 概率
                  五行等概率随机,冰球/火球等概率随机。
                  .
                  3.2.2 冰火球的生成和移动
                  首先要说明,冰火球只有动画,而不是像僵尸或子弹这样的“实体”。僵王[+140]处是冰火球对应动画的ID,[+8]动画速度为2fps,重点关注动画[+2C]处的“横坐标偏移”,是个浮点值,可以看作冰火球的横坐标。
                  冰火球在僵王89状态第142(1~4路)/152(5路)帧生成,生成时横向偏移455,生成起第104帧开始移动。横向偏移<-180(具体<还是≤我看不懂)时消失。
                  冰火球的动画有_ground图层,其移动实际上是按照非匀速僵尸的机制来的,不过各个运动片段的时长基本一致,使得冰火球的运动基本是匀速的:火球有0.368px/cs、0.370px/cs、0.372px/cs三种瞬时速度,冰球在0.356px/cs、0.358px/cs、0.360px/cs三种瞬时速度(实际上小数点后5~6位会有微小浮动)(没错,冰球比火球略慢)。
                  另外,冰火球的生成可以被ICE3,而且僵王不像巨人那样收回去之后还会再检测丢不丢小鬼,冰火球的生成会被直接取消,详见【寒冰菇,飞贼僵尸与动画进度的不可不说的奇妙BUG】https://tieba.baidu.com/p/8808382073和【【PVZ】什么?寒冰菇居然可以消冰球???】https://www.bilibili.com/video/BV1tw411V7pc


                  IP属地:江苏10楼2025-05-25 23:23
                  回复
                    3.2.3 冰火球碾压植物
                    冰火球每帧进行碾压判定,先碾压植物后碾压小推车。判定碾压植物时,先将冰火球的横向偏移转化成列数,然后直接将所在格植物碾压。
                    列数转换如下:

                    化简一下就是:
                    列数=int((横向偏移+35)/80)+1,大于9改为9,小于0改为0(内存中列数从0开始,此处其实是小于-1则改为-1,本文按日常交流用语统一+1);横向偏移为-35时也是0,不过实际游戏中冰火球的横向偏移不会刚好为-35。
                    实际上刚生成时(455+35)/80+1=7.125即7列,已经小于9列了。
                    .
                    另外,与僵尸不同,冰火球每帧先移动再进行碾压判定,因此碾压判定时采用的是本帧坐标。


                    IP属地:江苏11楼2025-05-25 23:26
                    回复
                      3.2.4 冰火球碾压小推车
                      判定小推车的碾压时,将冰火球的横向偏移与小推车坐标比较,若冰火球横向偏移-50<小推车坐标<冰火球横向偏移,也就是小推车坐标<冰火球横向偏移<小推车坐标+50,则碾压。
                      静止在左侧的小推车坐标为-21,对应冰火球的碾压区间为-21<横向偏移<29。
                      一般来说小推车不会在冰火球右侧,例外情况是当小推车已经开过了7列冰火球才被吐出来。

                      如图,分别为刚碾到小推车的球(车-21,球-21.xxx)和刚好不碾到小推车的球(车505,球455)。
                      .
                      相关时间如下(理论计算与实测一致):


                      IP属地:江苏12楼2025-05-25 23:27
                      回复
                        3.3 蹦极
                        3.3.1 选格
                        三只蹦极分别位于1~5列中相邻的三列,三种情况等概率,不论有没有植物。出生顺序从左到右。
                        蹦极的选行和常规关卡一致;与常规关卡不同的是,僵王放的蹦极选行不会记录进各行“上次和上上次被选择”的记录,即不会影响其他僵尸的选行。
                        .
                        3.3.2 生成高度
                        相邻两行的纵向偏移差为85,刚好是屋顶格子的行高;相邻两列的纵向偏移差为20,刚好是斜坡上相邻格子的坐标差,也就是说视觉上所有蹦极都会出生在同一高度,如图:

                        考虑到蹦极僵尸编号大于僵王,在生成的本帧就会移动,实际生成的高度是在蹦极生成帧用ShowMe读到的数据+8(蹦极下落速度是8px/cs)。
                        不同位置蹦极的具体生成高度如下表:

                        实际游戏中6~9路不会出蹦极,此处是强行修改出来的。
                        .
                        3.3.3 蹦极状态变化
                        蹦极相关状态编号:4下落,6停留,7抓取,8上升。
                        由上表可以得出不同位置蹦极落下的时间(高度降至0时状态由4改为6,因此除一路5~9列外状态4持续的时间需-1,一路5~9列生成同帧状态即为6):

                        下落的蹦极高度降至0的同一帧切换为停留状态,对于一路5~9列,生成时状态即为6。然后停留状态持续300,抓取状态持续63(减速状态下则为125),上升状态持续75后消失——与常规蹦极一样,不受僵王控制。
                        .
                        3.3.4 蹦极回收
                        有蹦极开始上升或蹦极全部死亡时僵王开始进入回收蹦极状态(状态84),播放回收动画,由于蹦极后于僵王判定,因此实际上是最早上升的蹦极进入状态8的下一帧僵王的状态才变为84。
                        僵王开始播放回收动画时,如果有蹦极被黄油固定住,则该蹦极直接死亡;寒冰菇冻住不受该影响(不过这种情况非常难碰到)。
                        前面的“全部死亡”其实不准确,经过简单的测试,如果使用灰烬烧掉,要等灰烬动画消失才会开始回收。
                        蹦极的上升并不受僵王收手的影响,因此有可能僵王已经收手完了蹦极其实还没删除(不过反正都出图了玩家看不到~)。被烧成灰烬同理,灰烬状态持续299cs后删除。


                        IP属地:江苏13楼2025-05-25 23:31
                        回复
                          3.4 砸车
                          1~5列等概率随机挑选2*3的格子,不论有没有植物。


                          IP属地:江苏14楼2025-05-25 23:34
                          回复
                            3.5 跺脚
                            3.5.1 攻击范围
                            范围为相邻两行的6~8列,僵王关9列不可种植物,若用修改器调出则9列植物也会被踩扁。
                            与砸车不同,跺脚要先挑出可以踩到植物的地方,再在其中等概率随机。
                            .
                            3.5.2 没有可踩植物时的bug
                            如果检测到没有可以踩的植物,按理说应该什么都没发生就过去了,但游戏是这样处理的:

                            可以看到,僵王跺脚倒计时归零后,如果没有可踩的植物,就不会播放跺脚动画,但是仍然会进入跺脚状态;而正常情况下,僵王处于跺脚状态下,会根据跺脚动画的进度判断是否压扁植物和是否回到闲置状态,现在则变成根据闲置动画判断了。(注意闲置倒计时与闲置动画相互独立,闲置倒计时为0不代表闲置动画进度为0。)
                            判断是否踩扁植物要看动画进度是否达到阈值,阈值又根据目标行获得,但是此时没有处理过目标行,目标行还是上一次放僵尸/砸车/跺脚留下来的数据(三种动作的目标行用的是同一处内存)(当然不强行修改内存的话不会连续跺脚而不放僵尸)。
                            .
                            这样就会产生三种情况:
                            1. 僵王的动画发生抽搐。
                            这是因为闲置动画是循环播放的,僵王判断是否离开跺脚状态看的是动画播放次数是否大于0,如果此时闲置动画已经播放超过一次,就会立刻重新播放闲置动画。
                            正常来说,循环播放的动画,它的动画的第一帧和最后一帧应该要能接上,视觉上才不突兀,但现在从中间的某一帧一下子跳回到第一帧,视觉上就不对劲了。
                            2. 僵王压扁6~9列的所有植物,不播放跺脚动画,但是有踩扁的音效。
                            这需要已播放次数=0且动画进度未达到阈值,则动画进度达到阈值时会踩扁植物。如果僵王刚进入跺脚状态时没有搜索到植物,但是在压扁函数触发之前种下植物,则新种下的植物会被踩扁;即使没有植物,也会播放踩扁的音效。
                            之后动画播放完一次之后正常回到闲置状态并从头播放闲置动画。
                            3. 僵王不进行任何行为。
                            这需要已播放次数=0且动画进度已超过阈值,动画播放完一次之后正常回到闲置状态并从头播放闲置动画。


                            IP属地:江苏15楼2025-05-25 23:35
                            回复
                              2025-09-03 15:07:40
                              广告
                              不感兴趣
                              开通SVIP免广告
                              四、动画与时长

                              如图,图中时间数据由实测得到。其中理想状态下动画持续时长=ceiling[关键帧数/(动画速度/100)],但如果刚好整除,由于浮点数计算精度问题可能还需+1。
                              .
                              游戏通过动画进度判断事件是否触发时,条件是上一帧进度≤阈值且本帧进度≥阈值(且不处于暂停状态、倒放状态以及没有播放状态),且动画在同一帧内后于僵尸更新(所谓的本帧和上帧其实是上帧和上上帧),则如果动画进度在第t cs时达到或超过阈值,(t+1) cs僵尸更新时就会触发。
                              动画进度每帧的增量为(动画速度/100)/关键帧数,因此,动作发生的时间=ceiling(阈值/每帧的增量)+1
                              ⇒动作发生的时间=ceiling[阈值*关键帧数/(动画速度/100)]+1,如果刚好整除,由于浮点数计算精度问题可能还需+1。
                              .
                              状态82和83时播放的是连在一起的同一个动画,动画播放完毕后,动画会停留在最后一帧保持不动,直至回收蹦极。
                              吐球前后的持续时间由倒计时而非动画控制,此时动画循环播放。


                              IP属地:江苏16楼2025-05-25 23:38
                              回复