]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
strafehud: properly calculate per-frame acceleration
authorJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Sat, 6 Aug 2022 21:05:18 +0000 (23:05 +0200)
committerJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Sat, 10 Sep 2022 17:48:54 +0000 (19:48 +0200)
_hud_common.cfg
qcsrc/client/hud/panel/strafehud.qc
qcsrc/client/hud/panel/strafehud.qh

index 2817cffa29b9c5ced0294e6eb540ceece00b7b9b..1b54cbdf8a8ee4e7601e2810ca13885b335b9bb4 100644 (file)
@@ -201,6 +201,7 @@ seta hud_panel_strafehud_timeout_ground "0.03333333" "time (in seconds) after la
 seta hud_panel_strafehud_timeout_turn "0.1" "time (in seconds) after releasing the strafe keys before changing mode (visually more consistent hud while switching between left/right strafe turning)"
 seta hud_panel_strafehud_antiflicker_angle "0.01" "how many degrees from 0° to 180° the hud ignores if it could cause visual disturbances otherwise (and to counter rounding errors)"
 seta hud_panel_strafehud_antiflicker_speed "0.0001" "how many qu/s the hud ignores if it could cause visual disturbances otherwise (and to counter rounding errors)"
+seta hud_panel_strafehud_fps_update "0.5" "update interval (in seconds) of the frametime to calculate the optimal angle, smaller values may cause flickering"
 
 // hud panel aliases
 alias quickmenu "cl_cmd hud quickmenu ${* ?}"
index c021032d9134235f7bb9f90233a44d0921fcfe19..41059c5271089d3749c67509097c0fa27f0adec1 100644 (file)
@@ -94,6 +94,10 @@ void HUD_StrafeHUD()
         static float turnspeed;
         static float turnaccel;
         static bool fwd = true;
+        static float strafe_dt_time = 0;
+        static int strafe_dt_count = 0;
+        static float strafe_dt_sum = 0;
+        static float strafe_dt_avg = 0;
 
         // physics
         bool   onground                      = islocal ? IS_ONGROUND(strafeplayer) : !(strafeplayer.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
@@ -106,8 +110,10 @@ void HUD_StrafeHUD()
         float  maxspeed_phys                 = onground ? PHYS_MAXSPEED(strafeplayer) : PHYS_MAXAIRSPEED(strafeplayer);
         float  maxspeed                      = !autocvar__hud_configure ? maxspeed_phys * crouch_mod * water_mod : 320;
         float  movespeed;
+        float  bestspeed;
         float  maxaccel_phys                 = onground ? PHYS_ACCELERATE(strafeplayer) : PHYS_AIRACCELERATE(strafeplayer);
         float  maxaccel                      = !autocvar__hud_configure ? maxaccel_phys * crouch_mod * water_mod : 1;
+        float  frametime_phys;
         float  vel_angle                     = vectoangles(strafeplayer.velocity).y - (vectoangles(strafeplayer.velocity).y > 180 ? 360 : 0); // change the range from 0° - 360° to -180° - 180° to match how view_angle represents angles
         float  view_angle                    = PHYS_INPUT_ANGLES(strafeplayer).y;
         float  angle;
@@ -160,6 +166,27 @@ void HUD_StrafeHUD()
         if(!autocvar_hud_panel_strafehud_uncapped)
             arrow_size = max(arrow_size, 1);
 
+        // determine frametime
+        if((csqcplayer_status == CSQCPLAYERSTATUS_PREDICTED) && (input_timelength > 0))
+            frametime_phys = input_timelength;
+        else
+            frametime_phys = ticrate;
+
+        if(frametime_phys > .05) // server splits frames longer than 50 ms into two moves
+            frametime_phys /= 2;
+
+        // calculate average frametime
+        strafe_dt_sum += frametime_phys;
+        ++strafe_dt_count;
+
+        if(((time - strafe_dt_time) > autocvar_hud_panel_strafehud_fps_update) || (strafe_dt_time == 0))
+        {
+            strafe_dt_avg = strafe_dt_sum / strafe_dt_count;
+
+            strafe_dt_time = time;
+            strafe_dt_count = strafe_dt_sum = 0;
+        }
+
         // determine whether the player is pressing forwards or backwards keys
         if(islocal) // if entity is local player
         {
@@ -367,7 +394,9 @@ void HUD_StrafeHUD()
             }
         }
 
-        minspeed = autocvar_hud_panel_strafehud_switch_minspeed < 0 ? (movespeed - maxaccel) + antiflicker_speed : autocvar_hud_panel_strafehud_switch_minspeed;
+        maxaccel *= strafe_dt_avg * movespeed;
+        bestspeed = max(movespeed - maxaccel, 0);
+        minspeed = autocvar_hud_panel_strafehud_switch_minspeed < 0 ? bestspeed : autocvar_hud_panel_strafehud_switch_minspeed;
 
         // get current strafing angle ranging from -180° to +180°
         if(!autocvar__hud_configure)
@@ -469,8 +498,8 @@ void HUD_StrafeHUD()
         }
 
         // best angle to strafe at
-        bestangle = (speed > fabs(movespeed - maxaccel) ? acos(fabs(movespeed - maxaccel) / speed) * RAD2DEG * (direction < 0 ? -1 : 1) : 0);
-        prebestangle = (speed > fabs(movespeed) ? acos(fabs(movespeed) / speed) * RAD2DEG * (direction < 0 ? -1 : 1) : 0);
+        bestangle = (speed > bestspeed ? acos(bestspeed / speed) * RAD2DEG * (direction < 0 ? -1 : 1) : 0);
+        prebestangle = (speed > movespeed ? acos(movespeed / speed) * RAD2DEG * (direction < 0 ? -1 : 1) : 0);
         odd_bestangle = -bestangle - wishangle;
         bestangle -= wishangle;
         prebestangle -= wishangle;
@@ -696,7 +725,7 @@ void HUD_StrafeHUD()
             drawfill(panel_pos + eX * (indicator_direction ? 0 : panel_size.x - direction_size_horizontal.x) + eY * panel_size.y, direction_size_horizontal, autocvar_hud_panel_strafehud_direction_color, autocvar_hud_panel_strafehud_direction_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
         }
 
-        if(speed <= (fabs(movespeed - maxaccel) + antiflicker_speed) && !immobile)
+        if(speed <= bestspeed && !immobile)
         {
             bestangle_anywhere = true; // moving forward should suffice to gain speed
         }
index fb438ec4170e55df05b5c58c37458fb5884b6333..a390055bde96054f042a7f3275f84d894c92e948 100644 (file)
@@ -56,6 +56,7 @@ float autocvar_hud_panel_strafehud_timeout_ground = 0.03333333;
 float autocvar_hud_panel_strafehud_timeout_turn = 0.1;
 float autocvar_hud_panel_strafehud_antiflicker_angle = 0.01;
 float autocvar_hud_panel_strafehud_antiflicker_speed = 0.0001;
+float autocvar_hud_panel_strafehud_fps_update = 0.5;
 
 void HUD_Panel_DrawStrafeHUD(float, float, vector, float, int, int);
 vector StrafeHUD_mixColors(vector, vector, float);