欢迎光临散文网 会员登陆 & 注册

谈谈MC战斗(三)

2022-08-23 22:56 作者:道家深湖  | 我要投稿

上次我谈到衡量击退的价值,所以我做了个打点计时器。改进之后,计时器还会记录目标与我的高度差。

结论:

  1. 击退的XZ速度,是击退力度与原本XZ速度一半做叠加。因此,原本静止的物体受到0.4力度的击飞后,会在XZ方向以0.4的速度飞出。

  2. 玩家近战攻击生物时,击退的方向是两者中点的连线。

  3. 生存模式下,近战攻击距离为3格,修改REACH_DIST属性并不增长攻击距离(但理论上可以缩短);创造模式下影响,但可以忽略。

  4. 生物落地一瞬间会出现速度异常,加速后退。原因不明。

  5. 对于僵尸这种移速属性为0.23,实际移速为0.115的生物来说,一次0.4的击退,会让他最多倒退1.25格左右,大约花24刻它才能走回被击退的位置。

有一些事情必须先想清楚,那就是,MC的物理系统与现实有一定差别,这差别来自多方面:

  1. MC的时间并非连续的,而是按照刻(tick)来的。比如某个物体第一刻在(0,0,1)的位置,下一刻在(0,0,2)的位置,那么我们并不能说物体“在1.5刻时处于两者之间”,因为根本就不存在1.5刻。这与现实世界有1.5s、1.05s有很大不同。在进入量子力学的尺度之前,现实世界的物理是连续且可分的。MC在前端会做一个现实上的插值,但在实际计算碰撞的时候,很容易发生穿透——你玩游戏的时候之所以不会有明显的感受,都是因为后台做了弥补处理。

  2. MC具有阻力系统,所以并不是机械能守恒的。不过这个倒也很好说,看一眼它的阻力机制就知道了。不同的实体会有不同,是否处于水中也会对阻力有影响。

  3. 机械能守恒等在连续世界里,靠积分分散成立的东西,在MC里只能用来做近似估计。比如,你想通过起跳速度v%5E2%3D2gh%20来计算跳跃高度的话,那么你计算出来的只是近似高度,结果必须用excel等时机推演一下。比如,如果重力加速度是10,你以10的速度起跳,那么在连续世界里,h%3D%5Csqrt%7B%5Cfrac%7Bv%5E2%7D%7B2g%7D%20%7D%20%3D%5Csqrt%7B5%7D%20,但实际上,你会往上移动10格。因为,你的速度在这一个tick内都不会变化,所以直接上飞10格后停在空中,然后又10速下落了。

在这样一个不连续的世界,我们要如何定义“速度”?那必然是”下一刻和这一刻之间的位移”。为什么不是这一刻与上一刻的位移?因为在代码里有motion等变量,它们会指导这个物体下一刻移动到哪里,这样与编程里的概念对应较好。至于编程里为什么那么定义,我觉得但凡自己写过游戏里的运动系统的人都会知道,就不赘述了。

在现实世界里,速度的量纲和位移并不一致。另外,MC里的速度其实也有两种,一种是“格每秒”,一种是“格每刻”。本文讨论的基本都是“格每刻”。并且,假定MC里的方块边长为1米,这样说起来省事。

加了Y之后的统计结果

那个很尖锐的灰色线绘制在右边的副坐标轴上,蓝色和黄色的圆滑线绘制在左边的主坐标轴上。

黄色的线是僵尸和玩家的水平距离,蓝色线是僵尸与玩家的垂直距离,灰色线是僵尸相对玩家的水平速度。

上次就很奇怪为什么玩家的速度会有一次抖动,这次结合了垂直距离可知,僵尸在接触地面之前,往后倒退的速度会略微变快

Y,距离,距离变化

是的,还没接触地面,提前两帧左右,倒退的速度却自行变快。这怎么也讲不通。倒退的速度增加,本来只有被击退的第一帧而已。

我们都知道,在现实世界里,人类没法直接二段跳,忽略空气阻力的话,在空中怎么摆动身体都没法扭转重心运动的路线。但是,在MC世界里,你在空中按方向键的话,是可以控制水平速度的。

所以是僵尸自己控制了速度导致吗?那也说不通。如果是僵尸开始努力的话,不应该往后倒退得越来越猛,毕竟僵尸是朝着玩家扑过去的,而不是被吓得使劲往回跑。而且,这个事情必现,不是因为随机因素导致。在这里记录一下,留给以后看代码分析了。

看到这,我需要研究一个问题,那就是,我对僵尸的击退,会不会打歪。

如果你看过代码的话,你会知道,多数普通的attackEntityFrom都会造成力度0.4的击退。那么,玩家攻击的时候,击退的方向是玩家与怪物的连线,还是玩家的视野方向呢?

是哪种?是黄的

d1是两者的x距离,d0初始是两者的z距离。

这个怪异的循环是在干吗?他是在施加随机扰动,如果两者在xz平面的距离小于0.01,他就会把d0和d1随机设置一波,一直随机到大于0.01。这代码写的有点奇怪,for括号里的第三部分完全可以提取到循环体内,第一段完全可以提到循环外面,整体写成while循环才是正常人的写法。

然后,我们按照xz距离把参数传进去,进行击退。也就是说,如果两者距离大于等于0.01,那么击退就是以中心连线算的,并非按照玩家视野朝向。所以,我们忽略了两者连线的切向速度,这个研究方法并没有问题。(补充:击退附魔则是以玩家视野方向算,与此不一致,代码分析略)

被击退瞬间的情况

他被打之后,水平速度只有0.34,算上垂直速度也只有0.36。

0.4力度的击退为什么击飞后,目标的速度不是0.4呢?

我们看看击退的代码。

物体的原本x、z速度折半,然后把strength按照xz参数作为方向参量正交分解为速度。

也就是说,如果物体原本在x、z方向不运动的话,那么你对他进行0.4力度的击退,它的XZ初速度必为0.4。

僵尸原本在XZ平面以0.115的速度向玩家靠近,受到了一个0.4力度的反向击退,得到的新速度是0.4-0.115/2,约等于0.34,理论计算与实际吻合。Y方向独享一份,就不管他了。

好了,这一部分理清楚了,那么,到底一次击退有多大的价值呢?

一次实验结果

平均几次的实验结果来看,我们可以认为,一次击退大约能击退1.25米,生物想要恢复原本的移动速度大约需要20刻,但想走回被击飞前的位置,大约需要24刻。也就是说,如果你近战,稳定地用剑1秒(20刻)攻击一次僵尸的话,僵尸身后只要有个1.5m的空间往后飞,那么你可以稳定地确保僵尸离你越来越远,直到你打不中。

查看代码可以得知,玩家默认的REACH_DISTANCE为5.0,也就是说只要不超过代码里的额外限制的话,玩家可以攻击5米内的敌人……吗?

上一段NetHandlerPlayServer的代码。

如果你能看得见目标的话,那么你可以够到6m(36的平方根)的怪物;如果你看不见的话,只能打到3m的怪物(9的平方根)。即使你的REACH_DISTANCE再大也不能超过这个限制。

至于“能看见”的话,查看EntityLivingBase::canEntityBeSeen的代码:

这就知道了,只取决于视线上有没有实体方块挡住,有就会变严格。有人说了,那我视线被挡住,隔着墙不是根本打不到吗?实际上,因为延迟和动画插值等缘故,前端和后端可能有偏差。这里只是各自算各自的,前端判定了之后,后端再次判定罢了。

也就是说,普通情况下在开阔地带,玩家有5米的攻击距离,但是有了栅栏等在中间阻碍的话,3米的距离才比较稳妥。果真如此吗?实际上,我把自己用命令方块精确传送了一下,但是只能打掉三格以外的盔甲架。REACH_DISTANCE的含义还有待商榷?代码里,这玩意看起来确实是用来处理方块触及的。

乍一看稳了,就是根据属性算的
哈哈,又判定一次

严格来说,他确实先用触及距离做了判定,但是之后如果目标超过3格,目标实体就会被清掉了,设为MISS。

可我明明记得修改触及距离对攻击范围有效啊?所以我打开游戏,挂上我的阵地做成附魔。实测发现,在创造模式我能打五个,手变长后我可以多打一个盔甲架,但是生存模式,仍然只能打3格的盔甲架。好吧,那就是没有效果了。真遗憾,谨记3这个前端参数把。不过,前后端的不一致是不是给挂端留下了空间?

至于倒退速度的异常成因,以及对其他生物的分析,就留待下一篇记录了。到时候打断点看看代码。

谈谈MC战斗(三)的评论 (共 条)

分享到微博请遵守国家法律