Minecraft 击退距离的定量分析
本文旨在定量分析Minecraft中玩家被击退时的飞行距离。我们将从最简单的静止状态开始,逐步加入疾跑、连击等复杂条件,推导出通用的计算模型。
前置理论视频:BV164gMzAEkW
核心定义与符号约定
为防止歧义,首先明确本文的核心概念与数学符号:
| 术语 |
定义与说明 |
| 击退 |
实体从被命中瞬间开始,到其落回地面为止的整个运动过程。 |
| 击退距离 (D) |
击退过程中实体在水平面产生的净位移。**方向约定:与玩家被击退时的面朝方向相同为正 (+),相反为负 (-)**。 |
击退初速度 (V₀) |
服务器在击退开始时赋予实体的瞬时速度矢量。本文中,定义V₀的水平分量为M₀ |
玩家输入速度 (I) |
由WASD移动输入产生的加速度。地面疾跑时 I_g ≈ 0.1274,空中时 I_a ≈ 0.02548。 |
阻力系数 (f) |
每Tick速度衰减乘数。默认 f = 0.91。站在地面、攻击其他玩家,两者都会分别额外在 f 上乘以0.6。 |
Tick (t) |
游戏的时间单位,1 Tick = 0.05秒。文中的时序以击退发生的瞬间为 t = 0。 |
静止状态下的击退
情景与数据
此情景为最简模型,用于建立分析基准:
- 玩家状态:完全静止,无任何移动输入。
- 击退参数:水平初速度 M0=−0.4。
- 过程:玩家在 0 tick 被击退作用,10 tick 回到地面。(tick = 0,10时均在地面)
- 实验数据图:
速度计算
在无输入状态下,速度每Tick按阻力系数衰减。由于击退发生在t=0之初,且玩家起始于地面:
- Tick 1(地面):M1=M0×fground=M0×(0.6×0.91)
- Tick 2-10(空中):速度递推公式为 Mt=Mt−1×fair。
由此可推导出第 t Tick末的速度通项公式:
Mt=M0×0.6×0.91t−1(1≤t≤9)
位移计算与基准公式
位移在速度衰减前计算:
ΔDt=Mt−1
总击退距离为各Tick位移增量之和:
D静止=t=1∑10ΔDt=M0+t=2∑10(M0×0.6×0.91t−2)=M0×(1+0.6k=0∑80.91k)≈M0×4.470562
代入 M0=−0.4,得 D ≈ -1.7882248,与图中数据吻合。
此模型给出静止击退基准系数 K ≈ 4.4706:
D静止≈M0×K
保持疾跑状态的击退
情景
- 玩家状态:被击退前后全程按住疾跑。
- 击退参数:
M₀ = -0.4。
速度计算
设 M₀ 为第 t Tick开始时的速度(含方向,负值代表与面朝方向相反)。其更新规律为:
- 加速:先加上输入速度
I(恒正)。
- 移动:使用加速后的速度计算位移。
- 衰减:最后乘以阻力系数
f,得到下一Tick初速。
即:
Mt=(Mt−1+It−1)×ft−1
Iground=0.1274,Iair=0.02548
fground=0.6×0.91,fair=0.91
递推后可得:
Mt=M0j=0∏t−1fj+k=0∑t−1Ikj=k∏t−1fj
带入具体数值可得:
Mt=0.257631+(0.91)t−1(0.546M0−0.1880706)=0.257631−0.4064706×(0.91)t−1
位移计算与结果
第 t Tick的位移增量:
ΔDt=Mt−1+It−1
总击退距离:
D疾跑=t=1∑10(Mt−1+It−1)=K×M0+C≈4.4703×(−0.4)+1.48≈−0.30812
疾跑状态下高频点击(20 CPS)
核心机制
每次击中其他玩家,当前水平速度会乘以 0.6, 可以当作阻力来处理。
模型修正与计算
此规则可视为对每个Tick位移增量的全局缩放。因此,在疾跑模型的基础上,总位移近似为:
D20cps≈D疾跑×0.6=(4.4703×(−0.4)+1.48)×0.6≈0.2443
一般情况
求解击退距离函数
我们考虑击退过程持续 x 个 tick(1≤x≤10)。第 i 个 tick 的移动量 ΔPi 定义为:
ΔPi=Mi−1+Ii−1,
其中 Mi 是第 i tick 的动量,满足递推关系:
Mi=(Mi−1+Ii−1)×fi−1
前 x 个 tick 的击退距离 D(x) 为:
D(x)=i=1∑xΔPi=i=1∑x(Mi−1+Ii−1)=i=0∑x−1Mi+i=0∑x−1Ii
代入 Mi 的通项公式:
Mi=M0j=0∏i−1fj+k=0∑i−1Ikj=k∏i−1fj
得到:
D(x)=i=0∑x−1M0j=0∏i−1fj+k=0∑i−1Ikj=k∏i−1fj+i=0∑x−1Ii=M0i=0∑x−1j=0∏i−1fj+i=0∑x−1k=0∑i−1Ikj=k∏i−1fj+k=0∑x−1Ik
合并含 Ik 的项,交换求和顺序:
D(x)=M0i=0∑x−1j=0∏i−1fj+k=0∑x−1Ik1+i=k+1∑x−1j=k∏i−1fj
将系数写为统一形式(当 i=k 时,空乘积定义为 1):
1+i=k+1∑x−1j=k∏i−1fj=i=k∑x−1j=k∏i−1fj
因此,最终得到一般公式:
D(x)=M0i=0∑x−1j=0∏i−1fj+k=0∑x−1Iki=k∑x−1j=k∏i−1fj
其中 1≤x≤10,且所有空乘积定义为 1。
观察后不难发现:
- 距离公式是形如 D(x)=M0×A+B 的线性公式
- A=∑i=0x−1∏j=0i−1fj, 只与 fi 有关
- B=∑k=0x−1Ik∑i=kx−1∏j=ki−1fj, 与fi,Ik有关
- 击退距离与 M0 线性相关
分析函数
一般而言,有 x=10 ,即:
D=M0i=0∑9j=0∏i−1fj+k=0∑9Iki=k∑9j=k∏i−1fj
由于实际计算过于烦杂,这里提供Python程序求函数D:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import math
def calculateA(f): n = 10 A = 0.0
for i in range(n): product = 1.0 for j in range(i): product *= f[j] A += product
return A
def calculateB(f, I): n = 10 B = 0.0
for k in range(n): B_k = 0.0 for i in range(k, n): product = 1.0 for j in range(k, i): product *= f[j] B_k += product B += I[k] * B_k
return B
def main(): M0 = -0.24
f = [0.91 * 0.6 for _ in range(10)] I = [0.02548 for _ in range(10)]
f[0] = 0.546 * 0.6 I[0] = 0.1274
A = calculateA(f) B = calculateB(f, I) D = A * M0 + B
print(f"数值公式: D = {A} × M + {B}") print(f"代入 M = {M0} 计算:") print(f"击退距离 D = {D}")
if __name__ == "__main__": main()
|
以下,是通过脚本求得的一些距离公式参数:
| tick |
A |
B |
D |
| 0 |
4.47056 |
1.47996 |
-0.308264 |
| 1 |
3.08234 |
1.3031 |
0.0701655 |
| 2 |
2.38044 |
1.15909 |
0.20691 |
| 3 |
2.03085 |
1.03756 |
0.225219 |
| 4 |
1.86016 |
0.933692 |
0.189626 |
| 5 |
1.77908 |
0.845606 |
0.133974 |
| 6 |
1.74208 |
0.773022 |
0.0761913 |
| 7 |
1.72623 |
0.716549 |
0.0260559 |
| 8 |
1.7202 |
0.677326 |
-0.0107539 |
| 9 |
1.71847 |
0.656838 |
-0.0305512 |
- tick = 0 时,表示玩家不攻击
- tick = i 时候, 表示玩家前i tick进行了攻击
- 此处的 M0=−0.4
间隔点分析
原理分析
由于玩家的击退基本上可以分为两段
- Mi<0, 且逐渐减为0,对击退距离的贡献是负的
- Mi>0, 且逐渐增大,对击退距离的贡献是正的
要使得击退距离(D)最大,就得使得第一阶段尽量小,第二阶段尽量大,也就是第一阶段尽量大。
间隔点就是为了实现这一目标的,只在击退后点击x次,让前半段有点击的0.6阻力,后半段没有,尽量使得 D 最大。
最佳间隔点次数
到这里,通用公式的推导过于复杂,不便于分析,在这里通过python生成一些图表,来研究不同的 M0 下,最优的x选择
观察图表,发现:
- 即使是 -1 的击退,最优的x也只有4,不到10 tick的一半,意味着其实间隔点击需要的就是尽量快,0.05s的间隔,4次点击,总时间也只有0.2s
失误情况
由于间隔点非常依赖于对刀节奏,相对于连续点击,我们很有可能,被击退作用后x个Tick,才开始间隔点,漏掉了几个tick,我们使用python脚本模拟,2,4,6,8次间隔点,在空了x个Tick后才开始间隔点,与全程连续点的击退距离差
通过上图,我们可以把情况大致分为2类:
- ∣M0∣>0.2:
这种情况下,我们几乎没有对x(开始没打到人)的容忍度,即使是1tick没有点击到,即使是最佳的4次点击,也会使得间隔点劣于不用管对刀节奏的连续点
- ∣M0∣<0.2
这种情况下,无论多少x为多少,点击次数多少,间隔点总是优于连续点,但是一般来说,很少有服务器的∣M0∣会小于0.2,基本都在0.4以上(你可以利用前文的公式,直接算出服务器的M0来验证