Sprinting

From Minecraft Parkour Wiki
Other languages:

Sprinting is an essential mechanic that makes the player move faster and jump further.


Activation

Sprinting is activated with the Sprint key, or by double-tapping Forward (on ground only).

  • It can also be activated with the help of the backward key. In any case, the activation timer is 7 ticks.
  • If the Forward key isn't held, the player stops sprinting.
  • The player stops sprinting after 30 seconds, unless the Sprint key is held.
  • Sprinting is incompatible with Sneaking (except in 1.14+).
  • Colliding with a wall causes the player to stop sprinting on the next tick.
  • Sprinting in air is delayed by one tick (activates and deactivates one tick late)
  • Sprinting cannot be activated when hungry, using an item, or being affected by Blindness.


Speed

Sprinting is 30% faster than walking, granting a base acceleration of 0.13. The asymptotic speed on ground is ~0.286 m/t.

Additionally, when the player jumps while sprinting, they accelerate by 0.2 towards their facing (regardless of whether the player is strafing)

  • This means the player accelerates quickly when sprint-jumping, making it the best way to build speed.
  • Sprint-jumping sideways is actually slower than forward, and goes off-track. But it does have applications:
    • Useful for Backward Momentum, in cases where a regular sprint-jump would give too much speed.
    • Used in the "Sidestep" technique for jumps that require turning. (example)


Code

The following snippets of code deal with how sprinting is activated.

/* EntityPlayerSP.java */
public void onLivingUpdate()
{
    if (this.sprintingTicksLeft > 0)
    {
        --this.sprintingTicksLeft;

        if (this.sprintingTicksLeft == 0)
            this.setSprinting(false);
    }

    if (this.sprintToggleTimer > 0)
    {
        --this.sprintToggleTimer;
    }

    //Takes the player's actions from the previous tick.
    boolean prevJumping = this.movementInput.jump;
    boolean prevSneaking = this.movementInput.sneak;
    float f = 0.8F;
    boolean prevMovingForward = this.movementInput.moveForward >= f;
        
    //the movement input is updated (including moveForward - keep in mind it's multiplied by 0.3 when sneaking).
    this.movementInput.updatePlayerMoveState();

    [...]

    //LEGACY METHOD: the player wasn't moving forward on the previous tick but is now. Must be on ground.
    if (!this.isSprinting() && this.onGround && !prevSneaking && !prevMovingForward && this.movementInput.moveForward >= f && isntHungry && !this.isUsingItem() && !this.isPotionActive(Potion.blindness))
    {
        if (this.sprintToggleTimer <= 0 && !keyBindSprint.isKeyDown())
            this.sprintToggleTimer = 7; //the timer is 7 ticks
        else
            this.setSprinting(true);
        }
        
    //Activated when the player was moving forward on the previous tick
    if (!this.isSprinting() && this.movementInput.moveForward >= f && isntHungry && !this.isUsingItem() && !this.isPotionActive(Potion.blindness) && keyBindSprint.isKeyDown())
    {
        this.setSprinting(true);
    }

        
    if (this.isSprinting() && (this.movementInput.moveForward < f || this.isCollidedHorizontally || !isntHungry))
    {
        this.setSprinting(false);
    }

}



/* From Entity, EntityLivingBase, EntityPlayerSP */
public void setSprinting(boolean sprinting)
{
    this.setFlag(3, sprinting);

    EntityAttribute movementSpeed = this.getEntityAttribute(movementSpeed);

    if (movementSpeed.getModifier(sprintModifierUUID) != null)
        movementSpeed.removeModifier(sprintModifier);

    if (sprinting)
        movementSpeed.applyModifier(sprintModifier); //sprintModifier adds 0.3 to the multiplier.

    this.sprintingTicksLeft = sprinting ? 600 : 0;
}


Here is the simplified sequence of steps performed during a tick:

  1. Update sprinting status
  2. Calculate velocity and move the player
  3. Update groundMovementFactor and airMovementFactor (multiplied by 1.3 if sprinting), which affect movement speed.


The reason air sprinting activation is delayed by one tick is because the game fetches airMovementFactor when applying air movement (which is updated after the player has already moved). In contrast, when the player is on ground, the game gets the multiplier directly from movementSpeed, which is updated before moving (applies modifier in method setSprinting). groundMovementFactor is essentially useless in the case of Player entities.