From 1a0f006e4401edcfe459458ab8bf9d63b27476e6 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 30 Dec 2021 23:38:14 +0100 Subject: [PATCH] Improve camera smoothing when crouching Asymptoptic (ease-out) smoothing is now used instead of linear interpolation. This kind of smoothing is often used for camera crouching animations in modern FPS games. Since the crouch animation speed affects game balance, it's been tuned to take roughly the same duration as before. --- source/src/physics.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 016ba58394..c391363e72 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -445,7 +445,8 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) float chspeed = (pl->onfloor || pl->onladder || !pl->crouchedinair) ? 0.4f : 1.0f; - const bool crouching = pl->crouching || (pl->eyeheight < pl->maxeyeheight && pl->eyeheight > 1.1f); + // crouch transition is asymptotic, so allow jumping as soon as the player is *mostly* uncrouched + const bool crouching = pl->crouching || (pl->eyeheight < pl->maxeyeheight - 0.5f && pl->eyeheight > 1.1f); const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed*(crouching && pl->state != CS_EDITING ? chspeed : 1.0f)*(pl==player1 && isfly ? flyspeed : 1.0f); const float friction = water ? 20.0f : (pl->onfloor || isfly ? 6.0f : (pl->onladder ? 1.5f : 30.0f)); const float fpsfric = max(friction/curtime*20.0f, 1.0f); @@ -868,11 +869,20 @@ void jumpn(bool on) void updatecrouch(playerent *p, bool on) { - if(p->crouching == on) return; if(p->state == CS_EDITING) return; // don't apply regular crouch physics in editfly - const float crouchspeed = 0.6f; + + // asymptoptic smoothing of crouch view height (smoother than linear interpolation) + const float crouchanimspeedscale = 0.9f; + if (on) { + const float croucheyeheight = p->maxeyeheight*3.0f/4.0f; + p->eyeheightvel = -abs(p->eyeheight - croucheyeheight) * crouchanimspeedscale; + } else { + p->eyeheightvel = abs(p->eyeheight - p->maxeyeheight) * crouchanimspeedscale; + } + + if(p->crouching == on) return; + // only play a sound on crouching state change p->crouching = on; - p->eyeheightvel = on ? -crouchspeed : crouchspeed; if(p==player1) audiomgr.playsoundc(on ? S_CROUCH : S_UNCROUCH); } @@ -962,4 +972,3 @@ void entinmap(physent *d) // brute force but effective way to find a free spa d->resetinterp(); conoutf("can't find entity spawn spot! (%d, %d)", int(d->o.x), int(d->o.y)); } -