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;
}
}