潛行

From Minecraft Parkour Wiki
Revision as of 07:19, 23 June 2022 by Pjx1314 (talk | contribs) (Created page with "在 1.9+ 中,潜行将玩家的身高降低到 1.65m。在 1.14+ 中,潜行会进一步降低它,降至 1.5m。")
Other languages:

潛行是一種移動機制,可以減慢玩家的移動速度並讓他們避免從方塊上掉下來


激活方法

按下潛行鍵後會立即激活潛行,並在按下時保持激活狀態。

潛行與疾跑並不兼容。(1.14+除外)。


效果

當玩家在地面上時,潛行可以防止他們跌落 1 個方塊以上。

  • 當潛行到方塊邊緣時,速度是保持不變的,這對於特定的跳躍非常有用,如 無助跑3+1
  • 1.11+ 中,下限改為0.6b
  • 當玩家在潛行時落在方塊邊緣時會出現「shift glitch」,在這種情況下他們可能會掉下來(已在 1.16.2 中修復)。
  • 在某些情況下,玩家在地面上潛行時可能會意外地掉下來(範例)-- 在1.16.2中部分修復。

潛行時,玩家可以掛在梯子和藤蔓的一邊。

  • 玩家仍然可以像往常一樣爬上去,但只要玩家留在方塊範圍內就不能掉下來。
  • 一般來說,潛行使梯子跳躍更容易。

在 1.9+ 中,潛行將玩家的身高降低到 1.65m。在 1.14+ 中,潛行會進一步降低它,降至 1.5m。


Speed

Sneaking is 70% slower than walking, granting a base acceleration of 0.03, but it doesn't get applied the same way as walking and sprinting:

  • When sneaking forward, the ground acceleration is 0.03×0.98 = 0.0294, as expected.
  • When sneaking diagonally, the ground acceleration is 0.0294×2 ≈ 0.0416


Code

It is worth showcasing how sneaking is implemented, and why it's flawed.
/* In Entity.java, stripped of irrelevant code */
public void moveEntity(double dX, double dY, double dZ)
{
    double dX_intended = dX;
    double dY_intended = dY;
    double dZ_intended = dZ;
    boolean sneakingOnGround = this.onGround && this.isSneaking();
    
    if (sneakingOnGround)
    {
        double increment = 0.05;
</div>

        <div lang="en" dir="ltr" class="mw-content-ltr">
//check for furthest ground under player in the X axis (from initial position)
        while(dX != 0.0D && getCollidingBoundingBoxes(this.boundingBox.offset(dX,-1,0)).isEmpty())
        {
            if (dX < increment && dX >= -increment)
                dX = 0.0D;
            else if (dX > 0.0D)
                dX -= increment;
            else
                dX += increment;
</div>

            <div lang="en" dir="ltr" class="mw-content-ltr">
dX_intended = dX;
        }
                
        //check for furthest ground under player in the Z axis (from initial position)
        while(dZ != 0.0D && getCollidingBoundingBoxes(this.boundingBox.offset(0,-1,dZ)).isEmpty())
        {
            if (dZ < increment && dZ >= -increment)
                dZ = 0.0D;
            else if (dZ > 0.0D)
                dZ -= increment;
            else
                dZ += increment;
</div>

            <div lang="en" dir="ltr" class="mw-content-ltr">
dZ_intended = dZ;
        }
                
                
        //calculate definitive dX and dZ based on the previous limits.
        while(dX != 0.0D && dZ != 0.0D && getCollidingBoundingBoxes(this.boundingBox.offset(dX,-1,dZ)).isEmpty())
        {
            if (dX < increment && dX >= -increment)
                dX = 0.0D;
            else if (dX > 0.0D)
                dX -= increment;
            else
                dX += increment;
            dX_intended = dX;
</div>

                    
            <div lang="en" dir="ltr" class="mw-content-ltr">
if (dZ < increment && dZ >= -increment)
                dZ = 0.0D;
            else if (dZ > 0.0D)
                dZ -= increment;
            else
                dZ += increment;
            dZ_intended = dZ;
        }
    }
</div>

    <div lang="en" dir="ltr" class="mw-content-ltr">
... //move the player with the new values of dX and dZ (order of collisions: Y-X-Z)
}
Illustration of the code presented above. The red blocks are necessary for the player to sneak on top of the green block.