- 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.
This commit is contained in:
Mitchell Richters 2020-10-08 21:10:54 +11:00
parent 9bcdeae6cd
commit f35bec4a5d
4 changed files with 48 additions and 44 deletions

View file

@ -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)

View file

@ -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())));
}
};

View file

@ -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)

View file

@ -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;