45° 斜跑

From Minecraft Parkour Wiki
This page is a translated version of the page 45 Strafe and the translation is 100% complete.
Other languages:

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