From d79a5d256d7593a3633759f302ebc33cc7710ecb Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Fri, 12 Jun 2020 13:47:40 +1000 Subject: [PATCH] - fix joystick scaling for all games. * Repairs https://forum.zdoom.org/viewtopic.php?f=340&t=67239 and https://forum.zdoom.org/viewtopic.php?f=340&t=67933 * Values that come from GZDoom backend are too low to be suitable for the Build games which were dividing by 'analogExtent'. * Remove definition of analogExtent from all games and define in inputstate.h, then define joyaxesScale as 75% of analogExtent to provide a bit of headroom and not have a scale of 1.0 be full speed. * Invert the returned results of GetAxes() as the returned floats are reversed for build games. * Leverage scaleAdjustmentToInverval() on game-side code to consistently scale the input irrespective of frame rate, vsync etc. --- source/core/inputstate.cpp | 8 ++-- source/core/inputstate.h | 3 ++ source/duke3d/src/player.cpp | 15 ++++---- source/exhumed/src/player.cpp | 11 +++--- source/rr/src/player.cpp | 69 ++++++++++++++++------------------- source/sw/src/game.cpp | 24 ++++++------ 6 files changed, 61 insertions(+), 69 deletions(-) diff --git a/source/core/inputstate.cpp b/source/core/inputstate.cpp index c3ced8ba6..7df21cad6 100644 --- a/source/core/inputstate.cpp +++ b/source/core/inputstate.cpp @@ -195,9 +195,9 @@ void CONTROL_GetInput(ControlInfo* info) I_GetAxes(joyaxes); - info->dyaw += joyaxes[JOYAXIS_Yaw]; - info->dx += joyaxes[JOYAXIS_Side]; - info->dz += joyaxes[JOYAXIS_Forward]; - info->dpitch += joyaxes[JOYAXIS_Pitch]; + info->dyaw += -joyaxes[JOYAXIS_Yaw] * joyaxesScale; + info->dx += -joyaxes[JOYAXIS_Side] * joyaxesScale; + info->dz += -joyaxes[JOYAXIS_Forward] * joyaxesScale; + info->dpitch += -joyaxes[JOYAXIS_Pitch] * joyaxesScale; } } diff --git a/source/core/inputstate.h b/source/core/inputstate.h index ebf6db5d1..274047125 100644 --- a/source/core/inputstate.h +++ b/source/core/inputstate.h @@ -179,6 +179,9 @@ public: extern InputState inputState; +constexpr int analogExtent = 32767; // used as a divisor for scaling joystick input. +constexpr float joyaxesScale = (float)analogExtent * 0.75f; // used as a multiplier for scaling joystick input. + void CONTROL_GetInput(ControlInfo* info); int32_t handleevents(void); diff --git a/source/duke3d/src/player.cpp b/source/duke3d/src/player.cpp index 8f4891555..ffe1b8009 100644 --- a/source/duke3d/src/player.cpp +++ b/source/duke3d/src/player.cpp @@ -3053,6 +3053,8 @@ void P_GetInput(int const playerNum) if (elapsedInputTicks == currentHiTicks) return; + auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; + if (g_cheatBufLen > 1 || (pPlayer->gm & (MODE_MENU|MODE_TYPE)) || paused) { if (!(pPlayer->gm&MODE_MENU)) @@ -3084,7 +3086,6 @@ void P_GetInput(int const playerNum) int const turnAmount = playerRunning ? (NORMALTURN << 1) : NORMALTURN; constexpr int analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; - constexpr int analogExtent = 32767; // KEEPINSYNC sdlayer.cpp input_t input {}; @@ -3095,12 +3096,12 @@ void P_GetInput(int const playerNum) input.svel = -(info.mousex + strafeyaw) >> 3; strafeyaw = (info.mousex + strafeyaw) % 8; - input.svel -= info.dyaw * keyMove / analogExtent; + input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); } else { input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); } if (mouseaim) @@ -3110,11 +3111,9 @@ void P_GetInput(int const playerNum) if (!in_mouseflip) input.q16horz = -input.q16horz; - input.q16horz = fix16_ssub(input.q16horz, fix16_from_int(info.dpitch * analogTurnAmount / analogExtent)); - input.svel -= info.dx * keyMove / analogExtent; - input.fvel -= info.dz * keyMove / analogExtent; - - auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; + input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); if (buttonMap.ButtonDown(gamefunc_Strafe)) { diff --git a/source/exhumed/src/player.cpp b/source/exhumed/src/player.cpp index c235c2cbe..d9fd939dc 100644 --- a/source/exhumed/src/player.cpp +++ b/source/exhumed/src/player.cpp @@ -189,7 +189,6 @@ void PlayerInterruptKeys() int const turnAmount = playerRunning ? 12 : 8; int const keyMove = playerRunning ? 12 : 6; constexpr int const analogTurnAmount = 12; - constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp if (buttonMap.ButtonDown(gamefunc_Strafe)) { @@ -198,12 +197,12 @@ void PlayerInterruptKeys() input.xVel = -(info.mousex + strafeyaw) >> 6; strafeyaw = (info.mousex + strafeyaw) % 64; - input.xVel -= info.dyaw * keyMove / analogExtent; + input.xVel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); } else { input.nAngle = fix16_sadd(input.nAngle, fix16_sdiv(fix16_from_int(info.mousex), fix16_from_int(32))); - input.nAngle = fix16_sadd(input.nAngle, fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1))); + input.nAngle = fix16_sadd(input.nAngle, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); } g_MyAimMode = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); @@ -215,9 +214,9 @@ void PlayerInterruptKeys() if (!in_mouseflip) input.horizon = -input.horizon; - input.horizon = fix16_ssub(input.horizon, fix16_from_int(info.dpitch * analogTurnAmount / analogExtent)); - input.xVel -= info.dx * keyMove / analogExtent; - input.yVel -= info.dz * keyMove / analogExtent; + input.horizon = fix16_ssub(input.horizon, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); + input.xVel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); + input.yVel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); if (buttonMap.ButtonDown(gamefunc_Strafe)) { diff --git a/source/rr/src/player.cpp b/source/rr/src/player.cpp index 20e520e54..3248c0d8b 100644 --- a/source/rr/src/player.cpp +++ b/source/rr/src/player.cpp @@ -3202,6 +3202,13 @@ static int P_CheckLockedMovement(int const playerNum) return 0; } +static double elapsedInputTicks; + +static double scaleAdjustmentToInterval(double x) +{ + return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); +} + void P_GetInput(int const playerNum) { auto &thisPlayer = g_player[playerNum]; @@ -3209,9 +3216,8 @@ void P_GetInput(int const playerNum) auto const pSprite = &sprite[pPlayer->i]; ControlInfo info; - auto const currentHiTicks = timerGetHiTicks(); - double const elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; - + auto const currentHiTicks = timerGetHiTicks(); + elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; thisPlayer.lastInputTicks = currentHiTicks; if (elapsedInputTicks == currentHiTicks) @@ -3250,7 +3256,6 @@ void P_GetInput(int const playerNum) int const turnAmount = playerRunning ? (NORMALTURN << 1) : NORMALTURN; constexpr int analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; - constexpr int analogExtent = 32767; // KEEPINSYNC sdlayer.cpp input_t input {}; @@ -3261,12 +3266,12 @@ void P_GetInput(int const playerNum) input.svel = -(info.mousex + strafeyaw) >> 3; strafeyaw = (info.mousex + strafeyaw) % 8; - input.svel -= info.dyaw * keyMove / analogExtent; + input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); } else { input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); } if (mouseaim) @@ -3276,11 +3281,9 @@ void P_GetInput(int const playerNum) if (!in_mouseflip) input.q16horz = -input.q16horz; - input.q16horz = fix16_ssub(input.q16horz, fix16_from_int(info.dpitch * analogTurnAmount / analogExtent)); - input.svel -= info.dx * keyMove / analogExtent; - input.fvel -= info.dz * keyMove / analogExtent; - - auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; + input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); if (buttonMap.ButtonDown(gamefunc_Strafe)) { @@ -3631,9 +3634,8 @@ void P_GetInputMotorcycle(int playerNum) auto const pSprite = &sprite[pPlayer->i]; ControlInfo info; - auto const currentHiTicks = timerGetHiTicks(); - double const elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; - + auto const currentHiTicks = timerGetHiTicks(); + elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; thisPlayer.lastInputTicks = currentHiTicks; if (elapsedInputTicks == currentHiTicks) @@ -3668,17 +3670,14 @@ void P_GetInputMotorcycle(int playerNum) int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); constexpr int analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; - constexpr int analogExtent = 32767; // KEEPINSYNC sdlayer.cpp input_t input {}; input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); - input.svel -= info.dx * keyMove / analogExtent; - input.fvel -= info.dz * keyMove / analogExtent; - - auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); pPlayer->crouch_toggle = 0; @@ -3885,9 +3884,8 @@ void P_GetInputBoat(int playerNum) auto const pSprite = &sprite[pPlayer->i]; ControlInfo info; - auto const currentHiTicks = timerGetHiTicks(); - double const elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; - + auto const currentHiTicks = timerGetHiTicks(); + elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; thisPlayer.lastInputTicks = currentHiTicks; if (elapsedInputTicks == currentHiTicks) @@ -3922,17 +3920,14 @@ void P_GetInputBoat(int playerNum) int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); constexpr int analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; - constexpr int analogExtent = 32767; // KEEPINSYNC sdlayer.cpp input_t input {}; input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); - input.svel -= info.dx * keyMove / analogExtent; - input.fvel -= info.dz * keyMove / analogExtent; - - auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); pPlayer->crouch_toggle = 0; @@ -4134,9 +4129,8 @@ void P_DHGetInput(int const playerNum) auto const pSprite = &sprite[pPlayer->i]; ControlInfo info; - auto const currentHiTicks = timerGetHiTicks(); - double const elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; - + auto const currentHiTicks = timerGetHiTicks(); + elapsedInputTicks = currentHiTicks - thisPlayer.lastInputTicks; thisPlayer.lastInputTicks = currentHiTicks; if (elapsedInputTicks == currentHiTicks) @@ -4167,7 +4161,6 @@ void P_DHGetInput(int const playerNum) int const turnAmount = playerCrouch ? 2 : (playerRunning ? 16 : 8); constexpr int analogTurnAmount = 16; int const keyMove = playerCrouch ? 3 : (playerRunning ? 24 : 12); - constexpr int analogExtent = 32767; // KEEPINSYNC sdlayer.cpp input_t input {}; @@ -4178,12 +4171,12 @@ void P_DHGetInput(int const playerNum) input.svel = -(info.mousex + strafeyaw) >> 3; strafeyaw = (info.mousex + strafeyaw) % 8; - input.svel -= info.dyaw * keyMove / analogExtent; + input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); } else { input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_int(info.dyaw / analogExtent * (analogTurnAmount << 1))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); } if (mouseaim) @@ -4193,9 +4186,9 @@ void P_DHGetInput(int const playerNum) if (!in_mouseflip) input.q16horz = -input.q16horz; - input.q16horz = fix16_ssub(input.q16horz, fix16_from_int(info.dpitch * analogTurnAmount / analogExtent)); - input.svel -= info.dx * keyMove / analogExtent; - input.fvel -= info.dz * keyMove / analogExtent; + input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp index 2da921f61..73087bc05 100644 --- a/source/sw/src/game.cpp +++ b/source/sw/src/game.cpp @@ -240,8 +240,6 @@ void LoadingLevelScreen(void); uint8_t FakeMultiNumPlayers; int totalsynctics; -int turn_scale = 256; -int move_scale = 256; short Level = 0; SWBOOL ExitLevel = FALSE; @@ -2995,7 +2993,10 @@ getinput(SW_PACKET *loc, SWBOOL tied) int const running = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); int32_t turnamount; int32_t keymove; - constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp + + // The function DoPlayerTurn() scales the player's q16angvel by 1.40625, so store as constant + // and use to scale back player's aim and ang values for a consistent feel between games. + float const inputScale = 1.40625f; if (running) { @@ -3019,34 +3020,31 @@ getinput(SW_PACKET *loc, SWBOOL tied) if (tied) keymove = 0; - info.dz = (info.dz * move_scale)>>8; - info.dyaw = (info.dyaw * turn_scale)>>8; - int32_t svel = 0, vel = 0; fix16_t q16aimvel = 0, q16angvel = 0; if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop) { svel = -info.mousex; - svel -= info.dyaw * keymove / analogExtent; + svel -= scaleAdjustmentToInterval(info.dyaw * keymove / analogExtent); } else { - q16angvel = fix16_div(fix16_from_int(info.mousex), fix16_from_int(45)); - q16angvel += fix16_from_int(info.dyaw * (turnamount << 1) / (analogExtent >> 1)); + q16angvel = fix16_div(fix16_from_int(info.mousex), fix16_from_int(inputScale * 32)); + q16angvel += fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * turnamount / (inputScale * (analogExtent >> 1)))); } if (mouseaim) - q16aimvel = -fix16_div(fix16_from_int(info.mousey), fix16_from_int(77)); + q16aimvel = -fix16_div(fix16_from_int(info.mousey), fix16_from_int((inputScale / 2) * 64)); else vel = -(info.mousey >> 6); if (in_mouseflip) q16aimvel = -q16aimvel; - q16aimvel -= fix16_from_int(info.dpitch) * turnamount / analogExtent; - svel -= info.dx * keymove / analogExtent; - vel -= info.dz * keymove / analogExtent; + q16aimvel -= fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * turnamount / ((inputScale / 2) * analogExtent))); + svel -= scaleAdjustmentToInterval(info.dx * keymove / analogExtent); + vel -= scaleAdjustmentToInterval(info.dz * keymove / analogExtent); if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop) {