疾跑
疾跑是一个很重要的机制,它使玩家移动得更快,跳得更远。
触发
疾跑是通过疾跑键或双击前进(仅在地面)触发的。
- 它还可以借助后退键进行激活。无论如何,激活时间都为 7 刻以内。
- 如果没有按住前进键,玩家就会停止疾跑。
- 除非按住疾跑键,否则玩家在 30 秒后停止疾跑。
- 不能在疾跑的同时潜行。(除了在 1.14 以上版本)。
- 与墙相撞会导致玩家在下一刻停止疾跑。
- 在空气中疾跑会延迟 1 刻(触发和停止会晚 1 刻)
- 饥饿、使用物品或受失明影响时,不能触发疾跑。
速度
疾跑的速度比无疾跑快 30%,给予的基本加速度为 0.13。在地面上的渐进速度是 ~0.286m/t。
此外,当玩家在疾跑时跳跃,会向其所朝的方向加速 0.2(不管玩家是否在斜跑)。
- 这意味着玩家在疾跑跳跃时加速很快,使其成为提高速度的最佳方式。
- 侧键疾跑跳跃实际上比前进疾跑跳跃慢,而且方向会偏离。但它确实有用途:
- 用于 Backward Momentum,在普通的疾跑跳跃会带来太多速度的情况下。
- 用于旋转跳的“Sidestep”技巧。(示例)
代码
下面的代码片段与触发疾跑有关。/* EntityPlayerSP.java */
public void onLivingUpdate()
{
if (this.sprintingTicksLeft > 0)
{
--this.sprintingTicksLeft;
if (this.sprintingTicksLeft == 0)
this.setSprinting(false);
}
if (this.sprintToggleTimer > 0)
{
--this.sprintToggleTimer;
}
//获取玩家在上 1 tick 中的行动。
boolean prevJumping = this.movementInput.jump;
boolean prevSneaking = this.movementInput.sneak;
float f = 0.8F;
boolean prevMovingForward = this.movementInput.moveForward >= f;
//运动输入被更新(包括moveForward——在潜行时它会被乘以0.3)。
this.movementInput.updatePlayerMoveState();
[...]
//遗留方法:玩家在之前的 Tick 中没有向前移动,但现在移动了。必须在地面上。
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; //时间是 7 刻
else
this.setSprinting(true);
}
//当玩家在上一刻上向前移动时激活
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);
}
}
/* 来自 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 会给 multiplier 加上 0.3。
this.sprintingTicksLeft = sprinting ? 600 : 0;
}
以下是在 1 刻中执行的简化步骤顺序:
- 更新疾跑状态
- 计算速度并移动玩家
- 更新
groundMovementFactor
和airMovementFactor
(疾跑的话乘以 1.3),影响移动速度。
空中疾跑的触发之所以会延迟 1 刻,是因为应用空中移动时游戏获取了 airMovementFactor
(在玩家已经移动后更新)。于此相反,当玩家在地面上时,游戏直接从 movementSpeed
中获得乘数,在移动之前更新(在 setSprinting
中获取修饰符)。对于玩家实体 groundMovementFactor
本质上是无用的。