8. Surfing and wallstrafingΒΆ

Surfing is a very specialised technique in Half-Life that is crucial in surf maps. The act of surfing involves accelerating against a sloped wall, thereby allowing some control over the vertical position of the player that is not possible by pure strafing alone. On the other hand, wallstrafing refers to the act of accelerating against a vertical wall, ideally with as much horizontal acceleration as possible.

While these two techniques are seemingly different, at least in their objectives, wallstrafing can be considered a degenerative case where the wall is perfectly vertical rather than sloped. The techniques for analysis is somewhat similar for the two cases, at least for the simplest cases, therefore we will discuss the two techniques in the same chapter.

8.1. WallstrafingΒΆ

Note

TODO: reword

The collision equation is

𝐯𝑐=π―β€²βˆ’π‘(𝐯′⋅ˆ𝐧)ˆ𝐧

where 𝐯′ is the velocity produced by the FME. Assuming 𝑏 =1, the speed is given by

‖𝐯𝑐‖2=𝐯𝑐⋅𝐯𝑐=‖𝐯′‖2βˆ’(𝐯′⋅ˆ𝐧)2

On the other hand, from the FME we have

𝐯′=𝐯+πœ‡Λ†π―π‘…(πœƒ)

where 𝑅(πœƒ) is the rotation matrix. Performing dot product with the plane normal ˆ𝐧 gives

𝐯′⋅ˆ𝐧=𝐯⋅ˆ𝐧+πœ‡Λ†π―π‘…(πœƒ)⋅ˆ𝐧

Assuming the initial velocity 𝐯 lies on the plane, we have 𝐯 ⋅ˆ𝐧 =0. On the other hand, ˆ𝐯𝑅(πœƒ) ⋅ˆ𝐧 β‰ 0 because ˆ𝐯 is being rotated out of the collision plane by πœƒ radians. It follows that the angle between the rotated ˆ𝐯 and ˆ𝐧 must be πœ‹/2 +πœƒ, or

𝐯′⋅ˆ𝐧=πœ‡cos⁑(πœ‹2+πœƒ)=βˆ’πœ‡sinβ‘πœƒ

As usual, the speed as a result of the FME is given by

‖𝐯′‖2=‖𝐯‖2+πœ‡2+2β€–π―β€–πœ‡cosβ‘πœƒ

Substituting back to the collision equation and simplifying yields

‖𝐯𝑐‖2=‖𝐯‖2+πœ‡2cos2β‘πœƒ+2β€–π―β€–πœ‡cosβ‘πœƒ

Let πœ‡ =𝛾1, then we can see that the speed is strictly decreasing in 0 β‰€πœƒ β‰€πœ‹.

Similarly, let πœ‡ =𝛾2, setting the derivative to zero and simplifying, we obtain,

0=(πΏβˆ’2‖𝐯‖cosβ‘πœƒ)(‖𝐯‖cos2β‘πœƒβˆ’πΏcosβ‘πœƒβˆ’β€–π―β€–)

It can be shown that

cosβ‘πœƒ=𝐿2‖𝐯‖

gives the maximum of the function.

Note

TODO: more commentary

8.2. Pure slidingΒΆ

Pure sliding turns out to be one of the fastest ways to gain horizontal speed down a sloped wall. One gains horizontal speed much faster asymptotically than strafing. This is not surprising when we consider the fact that the horizontal speed due to strafing increases roughly in proportion to the square root of time. By sliding down a plane, however, both the horizontal and vertical speed can potentially increase linearly with time, or constant acceleration.

Recall from the general collision equation (GCE) (see Player collision) that

𝐯𝑐=π―β€²βˆ’π‘(𝐯′⋅ˆ𝐧)ˆ𝐧

where 𝐯′ is the speed due to strafing and gravity and 𝑏 =1 is the assumed bounce coefficient. If no strafing is performed, we simply have

𝐯′=π―βˆ’βŸ¨0,0,π‘šπ‘”π‘”πœβŸ©

where π‘šπ‘” is 1/2 in the first frame and 1 for subsequent frame, to account for the leapfrog integrated gravitational field, as described in Gravity. To compute the GCE, we need to compute the dot product 𝐯′ ⋅ˆ𝐧. Assuming the initial velocity 𝐯 lies on the plane, then 𝐯 ⋅ˆ𝐧 =0. If the plane normal makes an angle of 0 ≀𝛼 β‰€πœ‹/2 with the horizontal plane, then we can write 𝑛𝑧 =sin⁑𝛼. What remains is therefore

𝐯′⋅ˆ𝐧=π‘šπ‘”π‘”πœcos⁑(πœ‹2+𝛼)=βˆ’π‘šπ‘”π‘”πœsin⁑𝛼

Eliminating the dot product and 𝐯′ from the GCE yields

𝐯𝑐=π―βˆ’βŸ¨0,0,π‘šπ‘”π‘”πœβŸ©+Λ†π§π‘šπ‘”π‘”πœsin⁑𝛼

Here we can see that

𝑣𝑐,𝑧=π‘£π‘§βˆ’π‘šπ‘”π‘”πœcos2⁑𝛼

while the horizontal speed is

β€–βŸ¨π‘£π‘,π‘₯,𝑣𝑐,π‘¦βŸ©β€–=√𝐴2+𝐴𝐡cos⁑𝛽+14𝐡2

where 𝐴 =βˆšπ‘£2π‘₯+𝑣2𝑦, 𝐡 =π‘šπ‘”π‘”πœsin⁑2𝛼, and 𝛽 is the angle between the projected velocity on the horizontal plane βŸ¨π‘£π‘₯,π‘£π‘¦βŸ© and the projected plane normal βŸ¨π‘›π‘₯,π‘›π‘¦βŸ©. In the worst case where 𝛽 =πœ‹/2, the horizontal speed increases roughly square root with time, but not for long, because 𝛽 gradually decreases over time as the component of velocity in the direction of the plane normal accelerates. In the best case where 𝛽 =0, the expression simplifies to

β€–βŸ¨π‘£π‘,π‘₯,𝑣𝑐,π‘¦βŸ©β€–=𝐴+12𝐡

That is, the horizontal speed accelerates linearly with time. This is also the steady state expression as 𝛽 drifts towards zero over time.

8.3. Vertical balance surfingΒΆ

Before tackling the harder issues on surfing, let’s tackle a basic movement strategy. When surfing on a slope, one can move vertically up or down depending on the strafing angle πœƒ. There must exist a critical πœƒ such that the vertical velocity will remain zero throughout, resulting in no vertical movement. As we shall see later, the horizontal speed would usually increase as usual, though at a lower acceleration than pure strafing.

In the GCE, the velocity 𝐯′ is due to the fundamental movement equation (FME) (described in detail in Air and ground movements) added to the gravitational step. Namely,

𝐯′=βŽ›βŽœ ⎜ ⎜ ⎜⎝𝐯+πœ‡π―βˆšπ‘£2π‘₯+𝑣2𝑦𝑅𝑧(πœƒ)⎞⎟ ⎟ ⎟ ⎟⎠diag⁑(1,1,0)+⟨0,0,π‘£π‘§βˆ’π‘šπ‘”π‘”πœβŸ©

A few notes to be made here. First, 𝐯 is a three-dimensional vector here, unlike the vectors in a typically written FME. Therefore, the rotation matrix is specifically a rotation about the 𝑧 axis, written as 𝑅𝑧(πœƒ). Second, diag⁑(π‘Ž1,…,π‘Žπ‘›) means a diagonal matrix with entries π‘Ž1,…,π‘Žπ‘›. By multiplying a vector with diag⁑(0,0,1), for example, we effectively zero out the π‘₯ and 𝑦 components. Indeed, the horizontal acceleration portion is multiplied by diag⁑(1,1,0) because the vertical component of the velocities are ignored in strafing and horizontal acceleration in general. Third, the gravity time step has a π‘šπ‘”, which has a value of π‘šπ‘” =1/2 for the first frame and π‘šπ‘” =1 for subsequent frames.

We now substitute 𝐯′ into the GCE. To compute the GCE, we perform the dot product 𝐯′ ⋅ˆ𝐧. The first term from the product may be written as

βŽ›βŽœ ⎜ ⎜ ⎜⎝𝐯+πœ‡π―βˆšπ‘£2π‘₯+𝑣2𝑦𝑅𝑧(πœƒ)⎞⎟ ⎟ ⎟ ⎟⎠diag⁑(1,1,0)⋅ˆ𝐧

Assume that the initial velocity 𝐯 lies on the plane, which makes 𝐯 ⋅ˆ𝐧 =0. Now 𝐯𝑅𝑧(πœƒ)diag⁑(1,1,0) ⋅ˆ𝐧 β‰ 0 because the velocity vector is being rotated away or into the plane. It follows that the angle between the two vectors is πœ‹/2 +|πœƒ| when projected onto the horizontal plane. The absolute value of πœƒ must be taken because the strafing angle can be negative. On the other hand, note that the plane normal projected onto the horizontal plane is no longer a unit vector, but rather, a vector of length cos⁑𝛼 where 𝛼 is the angle between the plane normal and the horizontal plane.

Using these observations, we find that the first term is equivalent to

πœ‡cos⁑(πœ‹2+|πœƒ|)cos⁑𝛼=βˆ’πœ‡sin⁑|πœƒ|cos⁑𝛼

The second term is easier to find. It is simply

(π‘£π‘§βˆ’π‘šπ‘”π‘”πœ)sin⁑𝛼

From the GCE, the final vertical velocity is given by

𝑣𝑐,𝑧=π‘£β€²π‘§βˆ’(𝐯′⋅ˆ𝐧)𝑛𝑧=π‘£π‘§βˆ’π‘šπ‘”π‘”πœβˆ’(βˆ’πœ‡sin⁑|πœƒ|cos⁑𝛼+(π‘£π‘§βˆ’π‘šπ‘”π‘”πœ)sin⁑𝛼)sin⁑𝛼

Assume that 𝑣𝑧 =𝑣𝑐,𝑧 =0, which is the steady state where no vertical movement occurs, the equation simplifies to

πœ‡sin⁑|πœƒ|sinβ‘π›Όβˆ’π‘šπ‘”π‘”πœcos⁑𝛼=0

This assumes 𝛼 β‰ πœ‹/2, which holds as long as the plane is not horizontal. Here, the usual analysis can be performed by assuming πœ‡ =𝛾1 or πœ‡ =𝛾2 and proceed to solve the equation. Empirical observations indicate that πœ‡ =𝛾2 is most frequently the admissible solution. Unfortunately, as is common in surfing analysis, writing down the solutions analytically is very difficult because it requires finding the roots of a quartic polynomial. It is much more practical to use a robust numerical method such as Brent’s method to find a solution, or by computing the eigenvalues of the associated companion matrix.

8.4. Maximum per-frame horizontal accelerationΒΆ

This section describes an attempt to optimise the horizontal acceleration on a surf plane. This approach involves maximising the horizontal acceleration on a per-frame basis. That is, this approach only considers the current frame without accounting for the acceleration in future frames. In isolation, as it turns out, it does not give us a global optimum. This serves to illustrate the danger of thinking in per-frame terms as is common in pure strafing, where, by luck, per-frame optimisations happen to also yield a global optimum. Attempting to maximise the accelerate per frame is a greedy algorithm, which in general is not guaranteed to give the most optimal configurations.

To illustrate this point, we will not derive an analytical expression for per-frame maximum acceleration. It suffices to use a numerical algorithm on a common Half-Life configuration, which consists of 𝐴 =100, 𝜏 =0.01 (for 100 fps), 𝑀 =320, and a surf plane of 𝛼 =30∘ such that βŸ¨π‘›π‘₯,𝑛𝑦,π‘›π‘§βŸ© =⟨0,cos⁑𝛼,sinβ‘π›ΌβŸ©. Assume an initial velocity of 𝐯 =⟨500,0,0⟩. One can check that the velocity and the plane normal are perpendicular.

8.5. Minimal time pathΒΆ