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.
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.