From f35bec4a5d9f18f06cefb084b6d2197e77070647 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Thu, 8 Oct 2020 21:10:54 +1100 Subject: [PATCH] - Fix interpolation issues and do other minor fixes following shift to fixedhoriz and binangle. * When interpolating on the initial setup, when binangle reached an overflow point when going lower than zero, the engine was spinning the player around clockwise to the new angle (2047, for instance). * Interpolating after casting as uint64_t with a workflow similar to the original games, the issue went away. * Cleaned up other interpolation functions to be of a consistent workflow. * Scale keyboard input turning down to degree speeds. * Uplift some remaining Q16.16 code in `applylook()` to full BAM precision. * Move static calculations of aim and look speeds for `sethorizon()` back into function since GameTicRate isn't set right before calculation is done. * Simplify the angle target setup back to a basic value like before. * Repair SW interpolation issues of weapon sprite drawer when rotating left/right. * Fix SW death horizon constant values following change of horizon center to 0. --- source/core/gamecontrol.cpp | 41 ++++++++++++++++++------------------- source/core/gamecontrol.h | 36 +++++++++++++++++--------------- source/sw/src/panel.cpp | 2 +- source/sw/src/player.cpp | 13 ++++++------ 4 files changed, 48 insertions(+), 44 deletions(-) diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index ea55c9a4d..62c5994d4 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -1501,12 +1501,12 @@ void processMovement(InputPacket* currInput, InputPacket* inputBuffer, ControlIn if (buttonMap.ButtonDown(gamefunc_Turn_Left) || (buttonMap.ButtonDown(gamefunc_Strafe_Left) && !allowstrafe)) { turnheldtime += scaleAdjust * turnheldamt; - currInput->avel -= scaleAdjust * (turnheldtime >= turboturntime ? turnamount : preambleturn); + currInput->avel -= scaleAdjust * (turnheldtime >= turboturntime ? turnamount : preambleturn) * (45. / 256.); } else if (buttonMap.ButtonDown(gamefunc_Turn_Right) || (buttonMap.ButtonDown(gamefunc_Strafe_Right) && !allowstrafe)) { turnheldtime += scaleAdjust * turnheldamt; - currInput->avel += scaleAdjust * (turnheldtime >= turboturntime ? turnamount : preambleturn); + currInput->avel += scaleAdjust * (turnheldtime >= turboturntime ? turnamount : preambleturn) * (45. / 256.); } else { @@ -1568,9 +1568,6 @@ void processMovement(InputPacket* currInput, InputPacket* inputBuffer, ControlIn // //--------------------------------------------------------------------------- -static double const aimamount = HorizToPitch(250. / GameTicRate); -static double const lookamount = HorizToPitch(500. / GameTicRate); - void sethorizon(fixedhoriz* horiz, float const horz, ESyncBits* actions, double const scaleAdjust) { // Store current horizon as true pitch. @@ -1586,24 +1583,26 @@ void sethorizon(fixedhoriz* horiz, float const horz, ESyncBits* actions, double if (*actions & (SB_AIM_UP|SB_AIM_DOWN)) { *actions &= ~SB_CENTERVIEW; + double const amount = HorizToPitch(250. / GameTicRate); if (*actions & SB_AIM_DOWN) - pitch -= scaleAdjust * aimamount; + pitch -= scaleAdjust * amount; if (*actions & SB_AIM_UP) - pitch += scaleAdjust * aimamount; + pitch += scaleAdjust * amount; } // this is the unlocked type if (*actions & (SB_LOOK_UP|SB_LOOK_DOWN)) { *actions |= SB_CENTERVIEW; + double const amount = HorizToPitch(500. / GameTicRate); if (*actions & SB_LOOK_DOWN) - pitch -= scaleAdjust * lookamount; + pitch -= scaleAdjust * amount; if (*actions & SB_LOOK_UP) - pitch += scaleAdjust * lookamount; + pitch += scaleAdjust * amount; } // clamp pitch after processing @@ -1638,25 +1637,25 @@ void sethorizon(fixedhoriz* horiz, float const horz, ESyncBits* actions, double void applylook(PlayerAngle* angle, float const avel, ESyncBits* actions, double const scaleAdjust, bool const crouching) { // return q16rotscrnang to 0 and set to 0 if less than a quarter of a unit - angle->rotscrnang -= q16look(xs_CRoundToInt(scaleAdjust * (angle->rotscrnang.asq16() * (15. / GameTicRate)))); - if (abs(angle->rotscrnang.asq16()) < (FRACUNIT >> 2)) angle->rotscrnang = q16look(0); + angle->rotscrnang -= bamlook(xs_CRoundToInt(scaleAdjust * angle->rotscrnang.asbam() * (15. / GameTicRate))); + if (abs(angle->rotscrnang.asbam()) < (BAMUNIT >> 2)) angle->rotscrnang = bamlook(0); // return q16look_ang to 0 and set to 0 if less than a quarter of a unit - angle->look_ang -= q16look(xs_CRoundToInt(scaleAdjust * (angle->look_ang.asq16() * (7.5 / GameTicRate)))); - if (abs(angle->look_ang.asq16()) < (FRACUNIT >> 2)) angle->look_ang = q16look(0); + angle->look_ang -= bamlook(xs_CRoundToInt(scaleAdjust * angle->look_ang.asbam() * (7.5 / GameTicRate))); + if (abs(angle->look_ang.asbam()) < (BAMUNIT >> 2)) angle->look_ang = bamlook(0); if (*actions & SB_LOOK_LEFT) { // start looking left - angle->look_ang -= q16look(FloatToFixed(scaleAdjust * (4560. / GameTicRate))); - angle->rotscrnang += q16look(FloatToFixed(scaleAdjust * (720. / GameTicRate))); + angle->look_ang -= bamlook(xs_CRoundToInt(scaleAdjust * (4560. / GameTicRate) * BAMUNIT)); + angle->rotscrnang += bamlook(xs_CRoundToInt(scaleAdjust * (720. / GameTicRate) * BAMUNIT)); } if (*actions & SB_LOOK_RIGHT) { // start looking right - angle->look_ang += q16look(FloatToFixed(scaleAdjust * (4560. / GameTicRate))); - angle->rotscrnang -= q16look(FloatToFixed(scaleAdjust * (720. / GameTicRate))); + angle->look_ang += bamlook(xs_CRoundToInt(scaleAdjust * (4560. / GameTicRate) * BAMUNIT)); + angle->rotscrnang -= bamlook(xs_CRoundToInt(scaleAdjust * (720. / GameTicRate) * BAMUNIT)); } if (*actions & SB_TURNAROUND) @@ -1672,15 +1671,15 @@ void applylook(PlayerAngle* angle, float const avel, ESyncBits* actions, double if (angle->spin.asbam() < 0) { // return spin to 0 - fixed_t add = FloatToFixed(scaleAdjust * ((!crouching ? 3840. : 1920.) / GameTicRate)); - angle->spin += q16look(add); + lookangle add = bamlook(xs_CRoundToUInt(scaleAdjust * ((!crouching ? 3840. : 1920.) / GameTicRate) * BAMUNIT)); + angle->spin += add; if (angle->spin.asbam() > 0) { // Don't overshoot our target. With variable factor this is possible. - add -= angle->spin.asq16(); + add -= angle->spin; angle->spin = bamlook(0); } - angle->ang += q16ang(add); + angle->ang += bamang(add.asbam()); } if (avel) diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 289bcc409..24eafda57 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -142,17 +142,18 @@ struct PlayerHorizon fixedhoriz interpolatedsum(double const smoothratio) { - fixedhoriz prev = ohoriz + ohorizoff; - fixedhoriz curr = horiz + horizoff; - return q16horiz(prev.asq16() + mulscale16(curr.asq16() - prev.asq16(), smoothratio)); + double const ratio = smoothratio / FRACUNIT; + fixed_t const prev = (ohoriz + ohorizoff).asq16(); + fixed_t const curr = (horiz + horizoff).asq16(); + return q16horiz(prev + xs_CRoundToInt(ratio * (curr - prev))); } }; struct PlayerAngle { - binangle ang, oang, target; + binangle ang, oang; lookangle look_ang, olook_ang, rotscrnang, orotscrnang, spin; - double adjustment; + double adjustment, target; void backup() { @@ -189,8 +190,8 @@ struct PlayerAngle { if (!cl_syncinput) { - target = bamang(xs_CRoundToUInt(value * BAMUNIT)); - if (target.asbam() == 0) target += bamang(1); + if (value == 0) value += (1. / BAMUNIT); + target = xs_CRoundToUInt(value * BAMUNIT); } else { @@ -201,14 +202,14 @@ struct PlayerAngle void processhelpers(double const scaleAdjust) { - if (target.asbam()) + if (target) { - ang = bamang(ang.asbam() + xs_CRoundToInt(scaleAdjust * (target - ang).asbam())); + ang = bamang(ang.asbam() + xs_CRoundToInt(scaleAdjust * (target - ang.asbam()))); - if (ang.asbam() - target.asbam() < BAMUNIT) + if (ang.asbam() - target < BAMUNIT) { - ang = target; - target = bamang(0); + ang = bamang(target); + target = 0; } } else if (adjustment) @@ -224,14 +225,17 @@ struct PlayerAngle binangle interpolatedsum(double const smoothratio) { - auto prev = oang.asbam() + olook_ang.asbam(); - auto curr = ang.asbam() + look_ang.asbam(); - return bamang(xs_CRoundToUInt(prev + fmulscale16(curr - prev, smoothratio))); + double const ratio = smoothratio / FRACUNIT; + int32_t const dang = UINT32_MAX / 2; + int64_t const prev = oang.asbam() + olook_ang.asbam(); + int64_t const curr = ang.asbam() + look_ang.asbam(); + return bamang(prev + xs_CRoundToUInt(ratio * (((curr + dang - prev) & 0xFFFFFFFF) - dang))); } lookangle interpolatedrotscrn(double const smoothratio) { - return bamlook(xs_CRoundToUInt(orotscrnang.asbam() + fmulscale16(rotscrnang.asbam() - orotscrnang.asbam(), smoothratio))); + double const ratio = smoothratio / FRACUNIT; + return bamlook(orotscrnang.asbam() + xs_CRoundToInt(ratio * (rotscrnang.asbam() - orotscrnang.asbam()))); } }; diff --git a/source/sw/src/panel.cpp b/source/sw/src/panel.cpp index c5aec6f7c..1b6294f1f 100644 --- a/source/sw/src/panel.cpp +++ b/source/sw/src/panel.cpp @@ -6921,7 +6921,7 @@ pDisplaySprites(PLAYERp pp, double smoothratio) short ang; int flags; - double look_anghalf = getHalfLookAng(pp->angle.look_ang.asq16(), pp->angle.look_ang.asq16(), cl_syncinput, smoothratio); + double look_anghalf = getHalfLookAng(pp->angle.olook_ang.asq16(), pp->angle.look_ang.asq16(), cl_syncinput, smoothratio); double looking_arc = fabs(look_anghalf) / 4.5; TRAVERSE(&pp->PanelSpriteList, psp, next) diff --git a/source/sw/src/player.cpp b/source/sw/src/player.cpp index 5f210adbb..53871be53 100644 --- a/source/sw/src/player.cpp +++ b/source/sw/src/player.cpp @@ -5592,7 +5592,7 @@ DoPlayerStopOperate(PLAYERp pp) } if (!cl_syncinput) - pp->angle.target = buildang(0); + pp->angle.target = 0; if (pp->sop_control) { @@ -5922,6 +5922,12 @@ DoPlayerDeathMessage(PLAYERp pp, PLAYERp killer) } +enum +{ + PLAYER_DEATH_HORIZ_UP_VALUE = 65, + PLAYER_DEATH_HORIZ_JUMP_VALUE = 50, + PLAYER_DEATH_HORIZ_FALL_VALUE = -50 +}; void DoPlayerBeginDie(PLAYERp pp) @@ -5942,11 +5948,6 @@ DoPlayerBeginDie(PLAYERp pp) DoPlayerDeathDrown, }; -#define PLAYER_DEATH_TILT_VALUE (32) -#define PLAYER_DEATH_HORIZ_UP_VALUE (165) -#define PLAYER_DEATH_HORIZ_JUMP_VALUE (150) -#define PLAYER_DEATH_HORIZ_FALL_VALUE (50) - if (Prediction) return;