45 Strafe
45° Strafe is a technique that grants more speed than regular movement.
It can be done by strafing and turning 45° degrees (hence the name).
45° Strafe can be performed by either:
- Turning 45° left and Strafing right.
- Turning 45° right and Strafing left.
The turning must be quick (< 1tick) and precise (at least ±11.5°, the closer to ±0° the better), so it's difficult to perform consistently.
Some jumps require the use of 45° strafe, such as 1bm 4.375b.
Effect on Movement
On every tick, the Player gains some acceleration depending on inputs and other factors.
- When moving forward (without strafing), the acceleration gained is scaled by
- 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.
Explanation
Below is a simplified version of the horizontal movement source code.
1 /*
2 * Code from Entity and EntityLivingBase
3 * Unnecessary or unrelated code is stripped out
4 */
5
6 public void onLivingUpdate()
7 {
8 /*
9 * moveStrafing and moveForward represent relative movement.
10 * moveStrafing = 1.0 if moving left, -1.0 if moving right, else 0.0
11 * moveForward = 1.0 if moving forward, -1.0 if moving backward, else 0.0
12 *
13 * Furthermore, moveStrafing and moveForward *= 0.3 if the player is sneaking.
14 */
15
16 this.moveStrafing *= 0.98F;
17 this.moveForward *= 0.98F;
18 this.moveEntityWithHeading(this.moveStrafing, this.moveForward);
19 }
20
21
22
23 public void moveEntityWithHeading(float strafe, float forward)
24 {
25 /* inertia determines how much speed is conserved onto the next tick */
26 float mult = 0.91F;
27 if (this.onGround)
28 {
29 /* Get slipperiness 1 block below the player */
30 mult *= getBlockSlipperinessAt(this.posX, this.getEntityBoundingBox().minY - 1, this.posZ);
31 }
32
33 /* acceleration = (0.6*0.91)^3 / (slipperiness*0.91)^3) */
34 float acceleration = 0.16277136F / (mult * mult * mult);
35
36 float movementFactor;
37 if (this.onGround)
38 movementFactor = this.landMovementFactor * acceleration;
39 /* base: 0.1; x1.3 if sprinting, affected by potion effects. */
40
41 else
42 movementFactor = this.airMovementFactor;
43 /* base: 0.02; x1.3 if sprinting */
44
45 this.updateMotionXZ(strafe, forward, movementFactor);
46 this.moveEntity(this.motionX, this.motionY, this.motionZ);
47
48 this.motionY -= 0.08D; /* gravity */
49 this.motionY *= 0.98D; /* drag */
50
51 this.motionX *= mult;
52 this.motionZ *= mult;
53 }
54
55
56
57 public void updateMotionXZ(float strafe, float forward, float movementFactor)
58 {
59 /*
60 * This function is responsible for the existence of 45° strafe. The geometry doesn't seem to make sense...
61 * Note that:
62 * - Sprint multiplier is contained within "movementFactor"
63 * - Sneak multiplier is contained within "strafe" and "forward"
64 * This is likely because Sneaking was implemented long before Sprinting
65 */
66 float distance = strafe * strafe + forward * forward;
67
68 if (distance >= 1.0E-4F)
69 {
70 distance = MathHelper.sqrt_float(distance);
71
72 if (distance < 1.0F)
73 distance = 1.0F;
74
75 distance = movementFactor / distance;
76 strafe = strafe * distance;
77 forward = forward * distance;
78 float sinYaw = MathHelper.sin(this.rotationYaw * Math.PI / 180.0F);
79 float cosYaw = MathHelper.cos(this.rotationYaw * Math.PI / 180.0F);
80 this.motionX += strafe * cosYaw - forward * sinYaw;
81 this.motionZ += forward * cosYaw + strafe * sinYaw;
82 }
83 }