45° 斜跑
45° 斜跑是一種能比常規運動獲取更多速度的技巧。
可以通過斜跑的同時轉向 45° 來實現(與其名相符)。
下列兩種方式均可實現 45° 斜跑:
- 向左轉 45° 並向右斜跑。
- 向右轉 45° 並向左斜跑。
轉向必須迅速(小於 1 刻)且精確(至少需要 ±11.5°,越接近 ±0° 加速越多),因此難以穩定使用。
一些跳躍必須使用 45° 斜跑來通過,比如 1bm 4.375b。
對運動的影響
在每一刻中,玩家基於按鍵輸入及其它因素來獲取加速度。
- 當向前移動(不使用斜跑)時,獲得的加速度為 倍
- 當斜跑時,獲得的加速度為 倍。
因此,45° 斜跑比正常移動要快 倍(約 2%)。
特殊情況:45° 潛行
- 當向前潛行(不使用斜跑)時,獲得的加速度為 倍
- 當潛行的同時斜跑時,獲得的加速度為 (≈1.386)倍
45° 潛行常用於無助跑跳躍(範例)。
除了跑酷之外,這個技巧也尤其常見於搭路,因為這比通常潛行的速度快了約 41%。
解釋
如下是水平運動原始碼的簡化版。
/*
* 代码来源于 Entity 和 EntityLivingBase
* 不必要与不相关的代码已被删去
*/
public void onLivingUpdate()
{
/*
* moveStrafing 与 moveForward 表示的是相对运动。
* 向左移动时 moveStrafing = 1.0,向右移动时 moveStrafing = -1.0,除此之外则为 0.0。
* 向前移动时 moveForward = 1.0,向后移动时 moveForward = -1.0,除此之外则为 0.0。
*
* 此外,玩家潜行时 moveStrafing 和 moveForward *= 0.3。
*/
this.moveStrafing *= 0.98F;
this.moveForward *= 0.98F;
this.moveEntityWithHeading(this.moveStrafing, this.moveForward);
}
public void moveEntityWithHeading(float strafe, float forward)
{
/* 模拟惯性,决定玩家有多少速度被保留到下一刻 */
float mult = 0.91F;
if (this.onGround)
{
/* 获取玩家下方 1 格方块的滑度 */
mult *= getBlockSlipperinessAt(this.posX, this.getEntityBoundingBox().minY - 1, this.posZ);
}
/* acceleration = (0.6*0.91)^3 / (slipperiness*0.91)^3) */
float acceleration = 0.16277136F / (mult * mult * mult);
float movementFactor;
if (this.onGround)
movementFactor = this.landMovementFactor * acceleration;
/* landMovementFactor 基础情况下为 0.1,疾跑时×1.3,受药水效果影响。 */
else
movementFactor = this.airMovementFactor;
/* airMovementFactor 基础情况下为 0.02,疾跑时×1.3 */
this.updateMotionXZ(strafe, forward, movementFactor);
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionY -= 0.08D; /* 重力 */
this.motionY *= 0.98D; /* 阻力 */
this.motionX *= mult;
this.motionZ *= mult;
}
public void updateMotionXZ(float strafe, float forward, float movementFactor)
{
/*
* 该函数导致了 45° 斜跑的存在。几何学在这里没有任何意义……
* 注意:
* - 疾跑的乘数位于 movementFactor 中
* - 潜行的乘数位于 strafe 和 forward 中
* 这可能是因为潜行在疾跑之前执行
*/
float distance = strafe * strafe + forward * forward;
if (distance >= 1.0E-4F)
{
distance = MathHelper.sqrt_float(distance);
if (distance < 1.0F)
distance = 1.0F;
distance = movementFactor / distance;
strafe = strafe * distance;
forward = forward * distance;
float sinYaw = MathHelper.sin(this.rotationYaw * Math.PI / 180.0F);
float cosYaw = MathHelper.cos(this.rotationYaw * Math.PI / 180.0F);
this.motionX += strafe * cosYaw - forward * sinYaw;
this.motionZ += forward * cosYaw + strafe * sinYaw;
}
}