- Separate pitch/yaw key input into separate functions and apply from the ticker.

This commit is contained in:
Mitchell Richters 2022-12-09 18:09:59 +11:00 committed by Christoph Oelckers
parent 470b4efac8
commit 2c592405fa
13 changed files with 91 additions and 113 deletions

View file

@ -67,24 +67,16 @@ inline static T getTicrateScale(const T value)
return T(value / GameTicRate);
}
inline static double getCorrectedScale(const double scaleAdjust)
inline static DAngle getscaledangle(const DAngle value, const DAngle object, const DAngle push)
{
// When using the output of I_GetInputFrac() to scale input adjustments at framerate, deviations of over 100 ms can occur.
// Below formula corrects the deviation, with 0.2125 being an average between an ideal value of 0.20 for 40Hz and 0.22 for 30Hz.
// We use the average value here as the difference is under 5 ms and is not worth complicating the algorithm for such precision.
return scaleAdjust < 1. ? scaleAdjust * (1. + 0.21 * (1. - scaleAdjust)) : scaleAdjust;
return (object.Normalized180() * getTicrateScale(value)) + push;
}
inline static DAngle getscaledangle(const DAngle value, const DAngle object, const DAngle push, const double scaleAdjust = 1)
{
return ((object.Normalized180() * getTicrateScale(value)) + push) * getCorrectedScale(scaleAdjust);
}
inline static void scaletozero(DAngle& object, const DAngle value, const double scaleAdjust = 1, const DAngle push = DAngle::fromDeg(32. / 465.))
inline static void scaletozero(DAngle& object, const DAngle value, const DAngle push = DAngle::fromDeg(32. / 465.))
{
if (auto sgn = object.Sgn())
{
object -= getscaledangle(value, object, push * sgn, scaleAdjust);
object -= getscaledangle(value, object, push * sgn);
if (sgn != object.Sgn()) object = nullAngle;
}
}
@ -169,56 +161,49 @@ void processMovement(InputPacket* const currInput, InputPacket* const inputBuffe
//---------------------------------------------------------------------------
//
// Player's horizon function, called from game's ticker or from gi->GetInput() as required.
// Adjust player's pitch by way of keyboard input.
//
//---------------------------------------------------------------------------
void PlayerAngles::applyPitch(float const horz, ESyncBits* actions, double const scaleAdjust)
void PlayerAngles::doPitchKeys(ESyncBits* actions, const bool stopcentering)
{
// Process mouse input.
if (horz)
{
activeAngles().Pitch += DAngle::fromDeg(horz);
*actions &= ~SB_CENTERVIEW;
}
// Cancel return to center if conditions met.
if (stopcentering) *actions &= ~SB_CENTERVIEW;
// Process keyboard input.
if (auto aiming = !!(*actions & SB_AIM_DOWN) - !!(*actions & SB_AIM_UP))
{
activeAngles().Pitch += getTicrateScale(PITCH_AIMSPEED) * scaleAdjust * aiming;
pActor->spr.Angles.Pitch += getTicrateScale(PITCH_AIMSPEED) * aiming;
*actions &= ~SB_CENTERVIEW;
}
if (auto looking = !!(*actions & SB_LOOK_DOWN) - !!(*actions & SB_LOOK_UP))
{
activeAngles().Pitch += getTicrateScale(PITCH_LOOKSPEED) * scaleAdjust * looking;
pActor->spr.Angles.Pitch += getTicrateScale(PITCH_LOOKSPEED) * looking;
*actions |= SB_CENTERVIEW;
}
// Do return to centre.
if ((*actions & SB_CENTERVIEW) && !(*actions & (SB_LOOK_UP|SB_LOOK_DOWN)))
{
const auto pitch = abs(activeAngles().Pitch);
const auto pitch = abs(pActor->spr.Angles.Pitch);
const auto scale = pitch > PITCH_CNTRSINEOFFSET ? (pitch - PITCH_CNTRSINEOFFSET).Cos() : 1.;
scaletozero(activeAngles().Pitch, PITCH_CENTERSPEED * scale, scaleAdjust);
if (!activeAngles().Pitch.Sgn()) *actions &= ~SB_CENTERVIEW;
scaletozero(pActor->spr.Angles.Pitch, PITCH_CENTERSPEED * scale);
if (!pActor->spr.Angles.Pitch.Sgn()) *actions &= ~SB_CENTERVIEW;
}
// clamp before we finish, even if it's clamped in the drawer.
activeAngles().Pitch = ClampViewPitch(activeAngles().Pitch);
pActor->spr.Angles.Pitch = ClampViewPitch(pActor->spr.Angles.Pitch);
}
//---------------------------------------------------------------------------
//
// Player's angle function, called from game's ticker or from gi->GetInput() as required.
// Adjust player's yaw by way of keyboard input.
//
//---------------------------------------------------------------------------
void PlayerAngles::applyYaw(float const avel, ESyncBits* actions, double const scaleAdjust)
void PlayerAngles::doYawKeys(ESyncBits* actions)
{
// add player's input
activeAngles().Yaw += DAngle::fromDeg(avel);
if (*actions & SB_TURNAROUND)
{
if (YawSpin == nullAngle)
@ -232,7 +217,7 @@ void PlayerAngles::applyYaw(float const avel, ESyncBits* actions, double const s
if (YawSpin < nullAngle)
{
// return spin to 0
DAngle add = getTicrateScale(!(*actions & SB_CROUCH) ? YAW_SPINSTAND : YAW_SPINCROUCH) * scaleAdjust;
DAngle add = getTicrateScale(!(*actions & SB_CROUCH) ? YAW_SPINSTAND : YAW_SPINCROUCH);
YawSpin += add;
if (YawSpin > nullAngle)
{
@ -240,7 +225,7 @@ void PlayerAngles::applyYaw(float const avel, ESyncBits* actions, double const s
add -= YawSpin;
YawSpin = nullAngle;
}
activeAngles().Yaw += add;
pActor->spr.Angles.Yaw += add;
}
}
@ -289,7 +274,7 @@ void PlayerAngles::doViewPitch(const DVector2& pos, DAngle const ang, bool const
else
{
// Make horizoff grow towards 0 since horizoff is not modified when you're not on a slope.
scaletozero(ViewAngles.Pitch, PITCH_HORIZOFFSPEED, 1, PITCH_HORIZOFFPUSH);
scaletozero(ViewAngles.Pitch, PITCH_HORIZOFFSPEED, PITCH_HORIZOFFPUSH);
}
// Clamp off against the maximum allowed pitch.

View file

@ -19,11 +19,9 @@ struct PlayerAngles
friend FSerializer& Serialize(FSerializer& arc, const char* keyname, PlayerAngles& w, PlayerAngles* def);
// Prototypes for applying input.
void applyPitch(float const horz, ESyncBits* actions, double const scaleAdjust = 1);
void applyYaw(float const avel, ESyncBits* actions, double const scaleAdjust = 1);
// Prototypes for applying view.
// Prototypes.
void doPitchKeys(ESyncBits* actions, const bool stopcentering);
void doYawKeys(ESyncBits* actions);
void doViewPitch(const DVector2& pos, DAngle const ang, bool const aimmode, bool const canslopetilt, sectortype* const cursectnum, bool const climbing = false);
void doViewYaw(const ESyncBits actions);
@ -39,10 +37,6 @@ struct PlayerAngles
}
// Render angle functions.
DRotator& activeAngles()
{
return !SyncInput() ? RenderAngles : pActor->spr.Angles;
}
DRotator lerpViewAngles(const double interpfrac)
{
return interpolatedvalue(PrevViewAngles, ViewAngles, interpfrac);

View file

@ -59,8 +59,8 @@ void GameInterface::GetInput(ControlInfo* const hidInput, double const scaleAdju
// Perform unsynchronised angle/horizon if not dead.
if (pPlayer->actor->xspr.health != 0)
{
pPlayer->Angles.applyYaw(input.avel, &pPlayer->input.actions, scaleAdjust);
pPlayer->Angles.applyPitch(input.horz, &pPlayer->input.actions, scaleAdjust);
pPlayer->Angles.RenderAngles.Yaw += DAngle::fromDeg(input.avel);
pPlayer->Angles.RenderAngles.Pitch += DAngle::fromDeg(input.horz);
}
}

View file

@ -1587,9 +1587,11 @@ void ProcessInput(PLAYER* pPlayer)
if (SyncInput())
{
pPlayer->Angles.applyYaw(pInput->avel, &pInput->actions);
pPlayer->actor->spr.Angles.Yaw += DAngle::fromDeg(pInput->avel);
}
pPlayer->Angles.doYawKeys(&pInput->actions);
if (!(pInput->actions & SB_JUMP))
pPlayer->cantJump = 0;
@ -1712,9 +1714,10 @@ void ProcessInput(PLAYER* pPlayer)
if (SyncInput())
{
pPlayer->Angles.applyPitch(pInput->horz, &pInput->actions);
pPlayer->actor->spr.Angles.Pitch += DAngle::fromDeg(pInput->horz);
}
pPlayer->Angles.doPitchKeys(&pInput->actions, pInput->horz);
doslopetilting(pPlayer);
pPlayer->slope = pPlayer->actor->spr.Angles.Pitch.Tan();

View file

@ -215,9 +215,9 @@ inline float PlayerInputAngVel(int pl)
return ps[pl].sync.avel;
}
inline float GetPlayerHorizon(int pl)
inline DAngle GetPlayerHorizon(int pl)
{
return ps[pl].sync.horz;
return DAngle::fromDeg(ps[pl].sync.horz);
}
inline void clearfriction()

View file

@ -835,8 +835,8 @@ void GameInterface::GetInput(ControlInfo* const hidInput, double const scaleAdju
if (p->GetActor()->spr.extra > 0)
{
// Do these in the same order as the old code.
p->Angles.applyYaw(p->adjustavel(input.avel), &p->sync.actions, scaleAdjust);
p->Angles.applyPitch(input.horz, &p->sync.actions, scaleAdjust);
p->Angles.RenderAngles.Yaw += p->adjustavel(input.avel);
p->Angles.RenderAngles.Pitch += DAngle::fromDeg(input.horz);
}
}

View file

@ -2704,7 +2704,6 @@ void processinput_d(int snum)
auto sb_fvel = PlayerInputForwardVel(snum);
auto sb_svel = PlayerInputSideVel(snum);
auto sb_avel = PlayerInputAngVel(snum);
auto psectp = p->cursector;
if (psectp == nullptr)
@ -2873,10 +2872,11 @@ void processinput_d(int snum)
//ENGINE calculates angvel for you
// may still be needed later for demo recording
sb_avel = p->adjustavel(sb_avel);
p->Angles.applyYaw(sb_avel, &actions);
p->GetActor()->spr.Angles.Yaw += p->adjustavel(PlayerInputAngVel(snum));
}
p->Angles.doYawKeys(&actions);
if (p->spritebridge == 0 && pact->insector())
{
int j = pact->sector()->floorpicnum;
@ -3107,9 +3107,11 @@ HORIZONLY:
if (SyncInput())
{
p->Angles.applyPitch(GetPlayerHorizon(snum), &actions);
p->GetActor()->spr.Angles.Pitch += GetPlayerHorizon(snum);
}
p->Angles.doPitchKeys(&actions, GetPlayerHorizon(snum).Sgn());
p->checkhardlanding();
//Shooting code/changes

View file

@ -3218,7 +3218,6 @@ void processinput_r(int snum)
auto sb_fvel = PlayerInputForwardVel(snum);
auto sb_svel = PlayerInputSideVel(snum);
auto sb_avel = PlayerInputAngVel(snum);
auto psectp = p->cursector;
if (p->OnMotorcycle && pact->spr.extra > 0)
@ -3485,10 +3484,11 @@ void processinput_r(int snum)
//ENGINE calculates angvel for you
// may still be needed later for demo recording
sb_avel = p->adjustavel(sb_avel);
p->Angles.applyYaw(sb_avel, &actions);
p->GetActor()->spr.Angles.Yaw += p->adjustavel(PlayerInputAngVel(snum));
}
p->Angles.doYawKeys(&actions);
if (p->spritebridge == 0 && pact->insector())
{
int j = pact->sector()->floorpicnum;
@ -3822,9 +3822,11 @@ HORIZONLY:
if (SyncInput())
{
p->Angles.applyPitch(GetPlayerHorizon(snum), &actions);
p->GetActor()->spr.Angles.Pitch += GetPlayerHorizon(snum);
}
p->Angles.doPitchKeys(&actions, GetPlayerHorizon(snum).Sgn());
p->checkhardlanding();
//Shooting code/changes

View file

@ -323,9 +323,9 @@ struct player_struct
void checkhardlanding();
void playerweaponsway(double xvel);
float adjustavel(float avel)
DAngle adjustavel(float avel)
{
return (psectlotag == ST_2_UNDERWATER)? avel * 0.875f : avel;
return DAngle::fromDeg((psectlotag == ST_2_UNDERWATER)? avel * 0.875f : avel);
}
void setCursector(sectortype* sect)

View file

@ -86,8 +86,8 @@ void GameInterface::GetInput(ControlInfo* const hidInput, double const scaleAdju
{
if (!nFreeze)
{
pPlayer->Angles.applyYaw(input.avel, &sPlayerInput[nLocalPlayer].actions, scaleAdjust);
pPlayer->Angles.applyPitch(input.horz, &sPlayerInput[nLocalPlayer].actions, scaleAdjust);
pPlayer->Angles.RenderAngles.Yaw += DAngle::fromDeg(input.avel);
pPlayer->Angles.RenderAngles.Pitch += DAngle::fromDeg(input.horz);
if (input.horz)
{

View file

@ -983,11 +983,12 @@ void AIPlayer::Tick(RunListEvent* ev)
// loc_1A494:
if (SyncInput())
{
Player* pPlayer = &PlayerList[nPlayer];
pPlayer->Angles.applyYaw(sPlayerInput[nPlayer].nAngle, &sPlayerInput[nLocalPlayer].actions);
UpdatePlayerSpriteAngle(pPlayer);
PlayerList[nPlayer].pActor->spr.Angles.Yaw += DAngle::fromDeg(sPlayerInput[nPlayer].nAngle);
}
PlayerList[nPlayer].Angles.doYawKeys(&sPlayerInput[nLocalPlayer].actions);
UpdatePlayerSpriteAngle(&PlayerList[nPlayer]);
// player.zvel is modified within Gravity()
double zVel = pPlayerActor->vel.Z;
@ -2470,9 +2471,11 @@ sectdone:
if (SyncInput())
{
pPlayer->Angles.applyPitch(sPlayerInput[nPlayer].pan, &sPlayerInput[nLocalPlayer].actions);
pPlayer->pActor->spr.Angles.Pitch += DAngle::fromDeg(sPlayerInput[nPlayer].pan);
}
pPlayer->Angles.doPitchKeys(&sPlayerInput[nLocalPlayer].actions, sPlayerInput[nPlayer].pan);
if (actions & (SB_AIM_UP | SB_AIM_DOWN) || sPlayerInput[nPlayer].pan)
{
pPlayer->nDestVertPan = pPlayer->pActor->spr.Angles.Pitch;

View file

@ -34,10 +34,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
BEGIN_SW_NS
void DoPlayerHorizon(PLAYER* pp, float const horz, double const scaleAdjust);
void DoPlayerTurn(PLAYER* pp, float const avel, double const scaleAdjust);
void DoPlayerTurnVehicle(PLAYER* pp, float avel, double z, double floor_dist);
void DoPlayerTurnTurret(PLAYER* pp, float avel);
void DoPlayerTurnVehicle(PLAYER* pp, DAngle& plyaw, float avel, double z, double floor_dist);
void DoPlayerTurnTurret(PLAYER* pp, DAngle& plyaw, float avel);
static InputPacket loc;
@ -182,22 +180,22 @@ void GameInterface::GetInput(ControlInfo* const hidInput, double const scaleAdju
{
if ((pp->Flags2 & PF2_INPUT_CAN_AIM))
{
DoPlayerHorizon(pp, input.horz, scaleAdjust);
pp->Angles.RenderAngles.Pitch += DAngle::fromDeg(input.horz);
}
if ((pp->Flags2 & PF2_INPUT_CAN_TURN_GENERAL))
{
DoPlayerTurn(pp, input.avel, scaleAdjust);
pp->Angles.RenderAngles.Yaw += DAngle::fromDeg(input.avel);
}
if ((pp->Flags2 & PF2_INPUT_CAN_TURN_VEHICLE))
{
DoPlayerTurnVehicle(pp, input.avel, pp->actor->getOffsetZ() + 10, abs(pp->actor->getOffsetZ() + 10 - pp->sop->floor_loz));
DoPlayerTurnVehicle(pp, pp->Angles.RenderAngles.Yaw, input.avel, pp->actor->getOffsetZ() + 10, abs(pp->actor->getOffsetZ() + 10 - pp->sop->floor_loz));
}
if ((pp->Flags2 & PF2_INPUT_CAN_TURN_TURRET))
{
DoPlayerTurnTurret(pp, input.avel);
DoPlayerTurnTurret(pp, pp->Angles.RenderAngles.Yaw, input.avel);
}
}

View file

@ -1523,19 +1523,7 @@ void UpdatePlayerSpriteAngle(PLAYER* pp)
//
//---------------------------------------------------------------------------
void DoPlayerTurn(PLAYER* pp, float const avel, double const scaleAdjust)
{
pp->Angles.applyYaw(avel, &pp->input.actions, scaleAdjust);
UpdatePlayerSpriteAngle(pp);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DoPlayerTurnVehicle(PLAYER* pp, float avel, double zz, double floordist)
void DoPlayerTurnVehicle(PLAYER* pp, DAngle& plyaw, float avel, double zz, double floordist)
{
SECTOR_OBJECT* sop = pp->sop;
@ -1553,10 +1541,10 @@ void DoPlayerTurnVehicle(PLAYER* pp, float avel, double zz, double floordist)
if (avel != 0)
{
auto sum = pp->Angles.activeAngles().Yaw + DAngle::fromDeg(avel);
auto sum = plyaw + DAngle::fromDeg(avel);
if (MultiClipTurn(pp, sum, zz, floordist))
{
pp->Angles.activeAngles().Yaw = sum;
plyaw = sum;
}
}
}
@ -1600,7 +1588,7 @@ void DoPlayerTurnVehicleRect(PLAYER* pp, DVector2* pos, DVector2* opos)
//
//---------------------------------------------------------------------------
void DoPlayerTurnTurret(PLAYER* pp, float avel)
void DoPlayerTurnTurret(PLAYER* pp, DAngle& plyaw, float avel)
{
DAngle new_ang, diff;
SECTOR_OBJECT* sop = pp->sop;
@ -1619,7 +1607,7 @@ void DoPlayerTurnTurret(PLAYER* pp, float avel)
if (fabs(avel) >= FLT_EPSILON)
{
new_ang = pp->Angles.activeAngles().Yaw + DAngle::fromDeg(avel);
new_ang = plyaw + DAngle::fromDeg(avel);
if (sop->limit_ang_center >= nullAngle)
{
@ -1634,10 +1622,10 @@ void DoPlayerTurnTurret(PLAYER* pp, float avel)
}
}
pp->Angles.activeAngles().Yaw = new_ang;
plyaw = new_ang;
}
OperateSectorObject(pp->sop, pp->Angles.activeAngles().Yaw, pp->sop->pmid);
OperateSectorObject(pp->sop, plyaw, pp->sop->pmid);
}
//---------------------------------------------------------------------------
@ -1679,17 +1667,6 @@ void DoPlayerSlopeTilting(PLAYER* pp)
//
//---------------------------------------------------------------------------
void DoPlayerHorizon(PLAYER* pp, float const horz, double const scaleAdjust)
{
pp->Angles.applyPitch(horz, &pp->input.actions, scaleAdjust);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DoPlayerBob(PLAYER* pp)
{
double amt;
@ -2087,9 +2064,12 @@ void DoPlayerMove(PLAYER* pp)
}
else
{
DoPlayerTurn(pp, pp->input.avel, 1);
pp->actor->spr.Angles.Yaw += DAngle::fromDeg(pp->input.avel);
}
pp->Angles.doYawKeys(&pp->input.actions);
UpdatePlayerSpriteAngle(pp);
pp->lastcursector = pp->cursector;
if (PLAYER_MOVING(pp) == 0)
@ -2209,9 +2189,11 @@ void DoPlayerMove(PLAYER* pp)
}
else
{
DoPlayerHorizon(pp, pp->input.horz, 1);
pp->actor->spr.Angles.Pitch += DAngle::fromDeg(pp->input.horz);
}
pp->Angles.doPitchKeys(&pp->input.actions, pp->input.horz);
DoPlayerSlopeTilting(pp);
if (pp->insector() && (pp->cursector->extra & SECTFX_DYNAMIC_AREA))
@ -2739,7 +2721,7 @@ void DoPlayerMoveVehicle(PLAYER* pp)
}
else
{
DoPlayerTurnVehicle(pp, pp->input.avel, zz, floordist);
DoPlayerTurnVehicle(pp, pp->actor->spr.Angles.Yaw, pp->input.avel, zz, floordist);
}
auto save_cstat = plActor->spr.cstat;
@ -2785,9 +2767,11 @@ void DoPlayerMoveVehicle(PLAYER* pp)
}
else
{
DoPlayerHorizon(pp, pp->input.horz, 1);
pp->actor->spr.Angles.Pitch += DAngle::fromDeg(pp->input.horz);
}
pp->Angles.doPitchKeys(&pp->input.actions, pp->input.horz);
DoPlayerSlopeTilting(pp);
DoTankTreads(pp);
@ -2815,7 +2799,7 @@ void DoPlayerMoveTurret(PLAYER* pp)
}
else
{
DoPlayerTurnTurret(pp, pp->input.avel);
DoPlayerTurnTurret(pp, pp->actor->spr.Angles.Yaw, pp->input.avel);
}
if (PLAYER_MOVING(pp) == 0)
@ -2829,9 +2813,11 @@ void DoPlayerMoveTurret(PLAYER* pp)
}
else
{
DoPlayerHorizon(pp, pp->input.horz, 1);
pp->actor->spr.Angles.Pitch += DAngle::fromDeg(pp->input.horz);
}
pp->Angles.doPitchKeys(&pp->input.actions, pp->input.horz);
DoPlayerSlopeTilting(pp);
}
@ -3393,9 +3379,11 @@ void DoPlayerClimb(PLAYER* pp)
}
else
{
DoPlayerHorizon(pp, pp->input.horz, 1);
pp->actor->spr.Angles.Pitch += DAngle::fromDeg(pp->input.horz);
}
pp->Angles.doPitchKeys(&pp->input.actions, pp->input.horz);
DoPlayerSlopeTilting(pp);
if (FAF_ConnectArea(pp->cursector))
@ -5971,8 +5959,11 @@ void DoPlayerDeathFollowKiller(PLAYER* pp)
}
else
{
DoPlayerTurn(pp, pp->input.avel, 1);
pp->actor->spr.Angles.Yaw += DAngle::fromDeg(pp->input.avel);
}
pp->Angles.doYawKeys(&pp->input.actions);
UpdatePlayerSpriteAngle(pp);
}
// follow what killed you if its available