understanding quake III movement

understanding quake III movement

Since quake III released their source code we can take a look at how movement is handled, which is in the file bg_move.c

After perusing around, you'll see that the method of interest is called PM_Accelerate which takes in wishdir, wishspeed and accel. At this point these are just parameters of the function, but wishdir actually reprents the players intended new direction based on their keyboard and mouse inputs.

It then computes the dot product of the players current horizontal velocity with wishdir and calls that currentspeed, note that this is not your current speed, but rather the length of the projection of your current horizontal velocity onto wishdir (assuming wishdir is a unit vector)

Next a new variable by the name of addspeed is created which is wishspeed - currentspeed, what this tells us is that whatever speed we wished to travel at is being reduced by current speed, therefore a better name for currentspeed is really speedpenalty

accelspeed is defined as accel * frametime * wishspeed, although the units don't really make sense here, accel * frametime is equal to a speed, and then wishspeed scales this speed up by an amount, in this sense we should think of wishspeed as the speed gained multiplier. After it is defined, we clamp it so that it is upperbounded by addspeed, which is speed we want the player to move at minus the penalty

finally we take wishdir, which we assume is a unit vector and scale it up by accelspeed and add it to the players current velocity, note that this means that accelspeed really represents a velocity gain.

how PM_Accelerate is called

PM_Accelerate is used in PM_[MovementType]Move, the two main ones we will cover are PM_WalkMove and PM_AirMove

Looking inside of PM_WalkMove, we'll ignore anything that has to do with water or flying. The first area of interest is when there is a check if the player is jumping, or rather just not touching the ground, if that's the case we simply use PM_AirMove which we will cover next.

Assuming that we're not jumping we can see that there is a call to PM_Friction, looking inside that method we can see that the vertical component of the players velocity is zeroed out (not sure why), and if your speed is under a certain length it gets zeroed out.

Next a variable by the name of drop is created which is intended to be the drop in your velocity based on the friction. If you are just normally walking in up to 1 unit of water and not being knocked back, then a variable called control which is equal to max(speed, pm_stopspeed) is used when we add control * pm_friction * frametime.

To understand this equation, we can think of pm_friction * frametime scaling the control by a certain amount which is independent of frame rate. Finally the newspeed is the current speed minus the drop in speed, and note newspeed is forced to stay non-negative.

Then we can get the ratio of the newspeed to the oldspeed, so newspeed / speed, so for example if we were travelling at 6 units per second, and then after subtracting the drop we are now at 3 units per second then, the speed ratio is 3/6 = 1/2, this ratio is then used to scale the players current velocity.


comments section