"Bunnyhopping" is an exploit of a very popular bug in games like Quake III Arena, Half-Life, and Counter-Strike. Bunnyhopping, or bhopping for short, allows a player to exceed the game-defined speed limit. It has created entirely new methods of play and allows very exciting, fast-paced emergent gameplay. As a decidedly skill-based mechanic, competitive players love bhopping because it is so hard to master. Thus, it may be useful to you as a game developer to "implement" bunnyhopping into your game. The purpose of this article is to define what bunnyhopping is, why it is important to consider as a game developer, and how to implement it mathematically into your FPS movement code. All code examples are open-source and free to use, as always.
This is what bunnyhopping looks like in-game to a skilled player:
One Example of Bunnyhopping in Counter-Strike: Source (Source)
The most important component of bunnyhopping is the concept of Air Strafing. In the clip above you may notice the player quickly wiggle his mouse left and right. When he does this, he syncs his mouse movement with his movement keys. That is, when he moves the mouse to the left he holds the a (left movement) key, and when he moves the mouse to the right he holds the d (right movement) key. The result of this from the player's perspective is a rapid increase in speed. This explains in part why bunnyhopping is such a skill-based mechanic. It takes great skill and accuracy to perfectly sync your mouse movement to your movement keys.
Explaining Air Strafing Mathematically
Air Strafing works because of the way movement acceleration is handled in the Quake Engine. It is possible in any game that is based off of the Quake engine, such as Source. If you would like you can check out the Quake III movement code or the Half Life 2 movement code on GitHub. Keep in mind that both codebases contain engine-specific code so they aren't as easy to integrate as the code in this article. Nevertheless it is still interesting to see the origins of the mechanic.
In the Quake III acceleration code, movement speed is limited in a very interesting and nonobvious way. Instead of limiting velocity directly, only the projection of the current velocity onto acceleration is limited. To explain this further, I need to first explain what vector projection is.
The projection of a vector a onto a vector b (also known as the component of a onto b) is "The orthagonal projection of a onto a straight line parallel to b" (To quote Wikipedia). This concept is illustrated below.
Figure 1: Projecting vector a onto vector b
Vector projection can be represented by the equation:
Vproj = |a| * cos( Θ ) = a • b̂
Above, • represents a dot product and b̂ is the unit vector of b (that is, a vector in the direction of b and a length of 1). The dot product notation works because a dot product is equal to |a| * |b| * cos(Θ). This is preferable because it is faster to perform than a cosine calculation.
Limiting the Projection
I'll repeat here what I said before: Instead of limiting velocity directly, only the projection of the current velocity onto acceleration is limited. This allows the player to exceed the maximum velocity in certain situations. Recall that in order to airstrafe you must sync your movement keys with your mouse movement. Let's model this mathematically:
Figure 2: Using projection to limit speed. "Time 0" is on the top left, Time 1 is on the top right, etc. Here is the key to this diagram:
Vc = The current velocity before any calculations Vw = The direction that the player wants to move in (the so-called wish direction). Vp = Vc projected onto Vw. Keep in mind that we are only considering magnitude in this calculation, so the direction of the projection doesn't matter.
Va = The acceleration to be added to Vp. The magnitude of this acceleration is server-defined. Vmax = The server-defined maximum velocity. If Vp + Va exceeds this, then Va is truncated.
In the above example, the player is both moving and turning left. After 4 physics ticks, Vp passes the server-defined speed limit Vmax and Va is truncated to account for this. Note, however, that Vc still substantially exceeds Vmax!
Here is my implementation of the above concepts in code:
Friction also plays an important role in bunnyhopping as well as Quake-style movment in general. Bunnyhopping earned its name because the player literally has to hop in order to gain speed. This is because if players didn't do this friction would reduce their speed.
Why, then, is it possible to bunnyhop at all? Wouldn't you always hit the ground and thus lose speed? This actually is not true in the Quake or Source engines because there is a 1-frame window where friction is not applied when the player hits the ground. This means that the player has a single frame to input the jump command without losing speed - another reason why bunnyhopping is so hard! If you want to retain the skill-based nature of bunnyhopping then be sure to add this delay into your physics calculations. If you want bhopping to be accessible to new players, you can add auto-bhopping where the player can simply hold space to automatically jump frame-perfectly.
The actual friction calculation is very simple, and looks like this in code:
Of course, friction is only applied when the player is grounded. friction is a server-defined variable of the approximate range 1-5. The higher friction is, the less slippery surfaces become. If you are familiar with console commands in the Source engine, you may recognize this variable as sv_friction.
Putting it All Together
Here is what all of this looks like in code:
Those of you who are familiar with the Source engine may once again recognize the sv_accelerate, sv_airaccelerate, and sv_friction convars in this code. Take some time to tweak these server-defined variables to your liking as they determine the feel of your game's movement.
That's it! This should be all you need to implement bunnyhopping into your game. If you have any questions or comments please feel free to post in the comments section below. Thank you for reading!
Quake III movement code - This is the original Quake engine movment code that "started it all". Check this out for nostalgia. There is a lot of engine-specific/messy code in there so watch out.
Source Engine movement code - This code was based off of the Quake engine code. However, it is a bit easier to decipher than the Quake engine. It also has some old code from an unreleased TF2 "Commander Mode" which is pretty cool.
F3Quake - Strafing Theory - This is a player-created mathematical analysis on strafe jumping which seeks to find the mathematically optimal air strafing strategy. It's an interesting read for any math nerd. It also details the worth of implementing bunnyhopping for the sake of a hardcore community.