Strafe-jumping is a movement technique in Quake 3 that allows the player to move much faster than the nominal run speed.
It was discovered as a bug in Quake II and fans liked it so much id software carried it forward to subsequent games.
why it’s fun
I played a lot of Quake 3 engine games, in particular Star Trek Voyager: Elite Force. Once you develop muscle memory for strafe jumping it’s extremely satisfying.
There’s a rhythm to it, and it feels like you’re running, one footfall after another. You drop into a flow state where everything else fades away—but if your attention wavers and you miss a beat, you stumble and kill your momentum.
It takes a lot of skill to keep up your speed while dodging enemies and returning fire. You only get a split second between strides to aim and take a shot before snapping back to the strafe.
what and how
YouTube: Quake Champions: All strafe jumping techniques
A proper strafe jump within Quake 3 can increase your UPS from 320 to over 600.
- Press the forward key
- Press the jump and left or right strafe key at the same time
- While in the air move the mouse in the direction of the strafe
- Jump immediately after landing
(Repeat steps two and three, alternating the strafe and turn with each jump.)
When landing, the player must jump immediately afterwards or else the ground friction will slow them down. When jumping, the player is unaffected by ground friction.
reddit: How to practice strafe-jumping?:
The most important thing is to synchronize your mouse movement with holding A+W or D+w. Once you land, jump again and switch directions, and always keep your eyes on the speedometer. The key is not to make huge movements, just SLIGHTLY, SMOOTHLY move your mouse in the direction of the strafe key you’re pressing and you will accelerate.
Once you get this down, try going into a game with bots. When aiming while strafejumping (while you’re in the air i mean) let go of all movement keys, hold space and look where you want, then look back to where you want to go. When you land you will immediately jump since you’re holding space. after you jump start pressing w and corresponding strafe keys again.
strafe jumping physics
How is strafe jumping implemented in the game engine physics code?
tl;dr:
re: acceleration… instead of limiting speed directly, only the component of velocity in the direction of acceleration is limited
why? it feels better if the player can accelerate sideways relative to their current velocity without killing their forward momentum
as a result there is no hard cap on speed… i.e., continuous acceleration is possible
but there are diminishing returns as greater and greater strafe-jumping precision is required to continue adding speed
also necessary: there is a one-frame window where friction is not applied after landing from a jump… without this, friction would bleed off any excess speed
acceleration code
Quake III bg_pmove.c:
/*
==============
PM_Accelerate
Handles user intended acceleration
==============
*/
static void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel ) {
#if 1
// q2 style
int i;
float addspeed, accelspeed, currentspeed;
currentspeed = DotProduct (pm->ps->velocity, wishdir);
addspeed = wishspeed - currentspeed;
if (addspeed <= 0) {
return;
}
accelspeed = accel*pml.frametime*wishspeed;
if (accelspeed > addspeed) {
accelspeed = addspeed;
}
for (i=0 ; i<3 ; i++) {
pm->ps->velocity[i] += accelspeed*wishdir[i];
}
#else
// proper way (avoids strafe jump maxspeed bug), but feels bad
...
#endif
}
parameters:
wishdir and wishspeed are the normalized unit vector and magnitude, respectively, of wishvel
somewhat confusingly, wishspeed is used as both the target velocity in the direction wishdir and as a base acceleration value
more confusingly, accel is not the acceleration, it’s a multiple used to adjust acceleration based on conditions (land, air, water, flying)
acceleration is calculed as accel wishspeed
accel values:
float pm_accelerate = 10.0f;
float pm_airaccelerate = 1.0f;
float pm_wateraccelerate = 4.0f;
float pm_flyaccelerate = 8.0f;
variables:
naming is pretty loose
e.g., currentspeed isn’t the magnitude of pm->ps->velocity as you might expect; it’s the component of the current velocity in the direction of wishdir
pseudocode
# component of current velocity in the direction of wishdir
# do nothing if it's already larger than wishspeed
return
# nominal change in velocity in the direction of wishdir
# don't overshoot wishspeed
# update velocity
further reading
Bunnyhopping from the Programmer’s Perspective
YouTube: Strafe-jumping physics explained
- great visualization but pseudocode and explanation are not exactly correct
- see detailed comment by @MistorDi:
Stack Exchange: Implementing strafe jumping
- discusses “Strafing Theory” by injx
reddit: Fully interactive strafejumping visualization tool
What is Strafe Jumping? by Dylan Lederle-Ensign & Noah Wardrip-Fruin in Transactions of the Digital Games Research Association