QW physics air

From QWiki
Revision as of 19:31, 17 January 2010 by *>Sss (New page: QW physics: moving in air, bunnyhop. With commands +forward +back +moveleft +moveright +moveup +movedown +speed player sets up values of forwardmove, sidemove, upmov...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

QW physics: moving in air, bunnyhop.


With commands

  +forward
  +back
  +moveleft
  +moveright
  +moveup
  +movedown
  +speed

player sets up values of forwardmove, sidemove, upmove variables.


Those values are defined by variables cl_sidespeed, cl_forwardspeed, cl_backspeed, cl_upspeed.


Also command +speed increases them 2 times.

If 2 opposite commands are (for example +forward and +back) then only earliest is really active.

Valuses forwardmove, sidemove, upmove are sent to server and also used in client to predict movement.

Code that processes player movement must be equal in client and server.

For example I have cl_forwardspeed 400 (ezquake default) and also there is following line in my config which is executed at the client start: +mlook;wait;+speed;wait;

Thus when pressing +forward

forwardmove = 2 * 400 = 800.


Movement of layers is processed in function PM_PlayerMove.


???? In ezquake under ktx server forwardmove = 800 for unknown (for me) reasons become 508 в PM_PlayerMove. ???

Lets see player movement in air. So called vector of wished speed is calculated. In air it is horizontal and is summed up from 2 components:

horyzontal vector with length forwardmove wich is directed along player view but horizontally

and of vector with length sidemove which is horizontal and perpendicular to 1st component.


     (Need picture.)

upmove is not used while in air. Only gravitation affects player movement in air.

Next , if length of received vector of wishspeed is grater than server restriction its length is decreased to meet restrictions.

This length is 320 for usual TDM and changes from 230 to 450 depending on player class in TF.


Next step. We are in function PM_PlayerAccelerate() and we have vector of wished direction with length 1 and value of wished speed.

First of all value of wished speed is restricted by 30: wishspd = min(wishspd, 30);

Then value of projection of current velocity to wished direction is calculated: currentspeed = DotProduct (pmove.velocity, wishdir);

Вычисляем разницу между желаемой скоростью и проекцией теущей скорости. Then difference between wished speed and projection of current velocity is calculated. If result is not positive then velocity does not change.

addspeed = wishspd - currentspeed; if (addspeed <= 0) return;


Then calculated value accelspeed = accel * wishspeed * pm_frametime =

            10 *320 * 0.014 = 44.8.

(wishspeed - is not wishspd here)

Then minimal value between is taken: accelspeed = min(accelspeed, addspeed);

Final step: vector with length accelspeed and direction wishdir is added to current velocity. VectorMA(pmove.velocity, accelspeed, wishdir, pmove.velocity);


Simpliest cases. If player is in air and does not press buttons his horizontal speed does not change.

If player has zero speed pressin +forward gives him speed 30 directed horizontally forward.

Now we can look into bunnyhop. Wewill concider speed greater than server restriction (320 in TDM) because player can gain that speed while he is on ground.

And of course we concder that player does not set too small values of cl_sidespeed, cl_forwardspeed, cl_backspeed.

Nice fact about QW is that it does not matter where player looking to. Only his wishdir is important.


Let angle between horizontal velocity v и wishdir is gamma.

wishspd = min(wishspd, 30) = 30 with conditions given above.

addspeed = wishspd - currentspeed = 30 - v * cos(gamma)

Final value of accelspeed >=0.

When bunnyhopping we want to increase speed so we must have

cos(gamma) > 0 addspeed = 30 - v * cos(gamma) > 0

When bunnyhopping value accel * wishspeed * pm_frametime is not important. Really 44.8 > 30 - v * cos(gamma) if cos(gamma) > -14.8/v that is only if we are decaccelerating.

So when bunnyhopping we have accelspeed = addspeed;


Increase of speed in one frame is dv_frame = addspeed * cos(gamma) = (30 - v * cos(gamma)) * cos(gamma).

Graphic of dv_frame(cos(gamma)) is parabola


       (Need picture)

Upper (best) point is when соs(gamma_best) = 15 / v;

Best possible increase in one frame is dv_frame_best = (30 - v * 15 / v) * 15 / v = 225 / v.

pm_frametime = 0.013, if 77fps phisics is active and pm_frametime = 0.014, if 72fps phisics (TF2003 standard, old TDM standard).

Ultimately speed increase is described by following differential equation:

        dv/dt = 225/(v * pm_frametime)


Acceleration with 77fps phisics is about 7% bigger than with 72fps.


v(t) ~ sqrt(t - t0).

QW has fundimental restriction: no entity can have speed bigger than 2000.

Theoretically it can be reached within 111 seconds with 77fps phisics.

Player must keep best direction of wishdir. He rotates to make it.

Player can look up or down while bunnyhopping: it does not matter for physics.

Correct angle speed is omega = addspeed * sin(gamma) / v = (15 / v) * sqrt(1 - (15 / v)^2).

So the greater is speed the less is best angle speed.

Comments and corrections are welcome.