45 Strafe/ja: Difference between revisions
Content added Content deleted
(Created page with "毎tick、プレイヤーはキー入力などの要素に基づいた加速度を得る。") |
(Created page with "* 正面に(strafe入力なしで)動いている場合、得られる加速度は<math>0.98</math>倍になる。") |
||
Line 25: | Line 25: | ||
毎tick、プレイヤーはキー入力などの要素に基づいた加速度を得る。 |
毎tick、プレイヤーはキー入力などの要素に基づいた加速度を得る。 |
||
* 正面に(strafe入力なしで)動いている場合、得られる加速度は<math>0.98</math>倍になる。 |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
* When moving forward (without strafing), the acceleration gained is scaled by <math>0.98</math> |
|||
</div> |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
<div lang="en" dir="ltr" class="mw-content-ltr"> |
Revision as of 11:19, 7 July 2022
45° Strafeとは、通常よりも高い速度を得られる技術である。
strafeキーを入力し、45°方向に振り向くことで実行できる(名前の由来はそこから)。
45° Strafeは以下のどちらでも可能:
- 左45°に振り向き、右Strafeキーを入力。
- 右45°に振り向き、左Strafeキーを入力。
振り向きは素早く(1tick以内)かつ正確(誤差最大±11.5°、±0°に近いほど良い)でなければならないため、安定して実行するのは難しい。
1bm 4.375bなど、45° strafeが必須のジャンプも存在する。
動きへの影響
毎tick、プレイヤーはキー入力などの要素に基づいた加速度を得る。
- 正面に(strafe入力なしで)動いている場合、得られる加速度は倍になる。
- When strafing, the acceleration is scaled by
Therefore, 45° Strafe is times faster than regular movement (about 2% faster).
Special case: 45° Sneak
- When sneaking forward (without strafing), the acceleration gained is scaled by
- When strafing while sneaking, the acceleration gained is scaled by (≈ 1.386)
45° Sneak is used for no momentum jumps (example).
Outside of parkour, it's notably used for bridging, as it's ~41% faster than regular sneaking.
解説
Below is a simplified version of the horizontal movement source code.
/*
* Code from Entity and EntityLivingBase
* Unnecessary or unrelated code is stripped out
*/
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
public void onLivingUpdate()
{
/*
* moveStrafing and moveForward represent relative movement.
* moveStrafing = 1.0 if moving left, -1.0 if moving right, else 0.0
* moveForward = 1.0 if moving forward, -1.0 if moving backward, else 0.0
*
* Furthermore, moveStrafing and moveForward *= 0.3 if the player is sneaking.
*/
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
this.moveStrafing *= 0.98F;
this.moveForward *= 0.98F;
this.moveEntityWithHeading(this.moveStrafing, this.moveForward);
}
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
public void moveEntityWithHeading(float strafe, float forward)
{
/* inertia determines how much speed is conserved onto the next tick */
float mult = 0.91F;
if (this.onGround)
{
/* Get slipperiness 1 block below the player */
mult *= getBlockSlipperinessAt(this.posX, this.getEntityBoundingBox().minY - 1, this.posZ);
}
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
/* acceleration = (0.6*0.91)^3 / (slipperiness*0.91)^3) */
float acceleration = 0.16277136F / (mult * mult * mult);
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
float movementFactor;
if (this.onGround)
movementFactor = this.landMovementFactor * acceleration;
/* base: 0.1; x1.3 if sprinting, affected by potion effects. */
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
else
movementFactor = this.airMovementFactor;
/* base: 0.02; x1.3 if sprinting */
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
this.updateMotionXZ(strafe, forward, movementFactor);
this.moveEntity(this.motionX, this.motionY, this.motionZ);
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
this.motionY -= 0.08D; /* gravity */
this.motionY *= 0.98D; /* drag */
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
this.motionX *= mult;
this.motionZ *= mult;
}
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
public void updateMotionXZ(float strafe, float forward, float movementFactor)
{
/*
* This function is responsible for the existence of 45° strafe. The geometry doesn't seem to make sense...
* Note that:
* - Sprint multiplier is contained within "movementFactor"
* - Sneak multiplier is contained within "strafe" and "forward"
* This is likely because Sneaking was implemented long before Sprinting
*/
float distance = strafe * strafe + forward * forward;
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
if (distance >= 1.0E-4F)
{
distance = MathHelper.sqrt_float(distance);
if (distance < 1.0F)
distance = 1.0F;
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
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;
}
}