Add a bunch of slope physics

I know giant commits all at once like this are a bad thing, but
too bad I worked without staging commits and now it's all here
at once :)
This commit is contained in:
RedEnchilada 2015-04-29 00:35:54 -05:00
parent 1f0f6b64c1
commit db883f6a23
5 changed files with 187 additions and 48 deletions

View file

@ -409,6 +409,50 @@ angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byt
} }
//
// RotateVector
//
// Rotates a vector around another vector
//
void M_VecRotate(v3fixed_t *rotVec, const v3fixed_t *axisVec, const angle_t angle)
{
// Rotate the point (x,y,z) around the vector (u,v,w)
fixed_t ux = FixedMul(axisVec->x, rotVec->x);
fixed_t uy = FixedMul(axisVec->x, rotVec->y);
fixed_t uz = FixedMul(axisVec->x, rotVec->z);
fixed_t vx = FixedMul(axisVec->y, rotVec->x);
fixed_t vy = FixedMul(axisVec->y, rotVec->y);
fixed_t vz = FixedMul(axisVec->y, rotVec->z);
fixed_t wx = FixedMul(axisVec->z, rotVec->x);
fixed_t wy = FixedMul(axisVec->z, rotVec->y);
fixed_t wz = FixedMul(axisVec->z, rotVec->z);
fixed_t sa = FINESINE(angle>>ANGLETOFINESHIFT);
fixed_t ca = FINECOSINE(angle>>ANGLETOFINESHIFT);
fixed_t ua = ux+vy+wz;
fixed_t ax = FixedMul(axisVec->x,ua);
fixed_t ay = FixedMul(axisVec->y,ua);
fixed_t az = FixedMul(axisVec->z,ua);
fixed_t xs = FixedMul(axisVec->x,axisVec->x);
fixed_t ys = FixedMul(axisVec->y,axisVec->y);
fixed_t zs = FixedMul(axisVec->z,axisVec->z);
fixed_t bx = FixedMul(rotVec->x,ys+zs);
fixed_t by = FixedMul(rotVec->y,xs+zs);
fixed_t bz = FixedMul(rotVec->z,xs+ys);
fixed_t cx = FixedMul(axisVec->x,vy+wz);
fixed_t cy = FixedMul(axisVec->y,ux+wz);
fixed_t cz = FixedMul(axisVec->z,ux+vy);
fixed_t dx = FixedMul(bx-cx, ca);
fixed_t dy = FixedMul(by-cy, ca);
fixed_t dz = FixedMul(bz-cz, ca);
fixed_t ex = FixedMul(vz-wy, sa);
fixed_t ey = FixedMul(wx-uz, sa);
fixed_t ez = FixedMul(uy-vx, sa);
rotVec->x = ax+dx+ex;
rotVec->y = ay+dy+ey;
rotVec->z = az+dz+ez;
}
@ -977,50 +1021,6 @@ boolean FV_IntersectedPolygon(const fvector_t *vPoly, const fvector_t *vLine, co
return false; return false;
} }
//
// RotateVector
//
// Rotates a vector around another vector
//
void FV_Rotate(fvector_t *rotVec, const fvector_t *axisVec, const angle_t angle)
{
// Rotate the point (x,y,z) around the vector (u,v,w)
fixed_t ux = FixedMul(axisVec->x, rotVec->x);
fixed_t uy = FixedMul(axisVec->x, rotVec->y);
fixed_t uz = FixedMul(axisVec->x, rotVec->z);
fixed_t vx = FixedMul(axisVec->y, rotVec->x);
fixed_t vy = FixedMul(axisVec->y, rotVec->y);
fixed_t vz = FixedMul(axisVec->y, rotVec->z);
fixed_t wx = FixedMul(axisVec->z, rotVec->x);
fixed_t wy = FixedMul(axisVec->z, rotVec->y);
fixed_t wz = FixedMul(axisVec->z, rotVec->z);
fixed_t sa = FINESINE(angle);
fixed_t ca = FINECOSINE(angle);
fixed_t ua = ux+vy+wz;
fixed_t ax = FixedMul(axisVec->x,ua);
fixed_t ay = FixedMul(axisVec->y,ua);
fixed_t az = FixedMul(axisVec->z,ua);
fixed_t xs = FixedMul(axisVec->x,axisVec->x);
fixed_t ys = FixedMul(axisVec->y,axisVec->y);
fixed_t zs = FixedMul(axisVec->z,axisVec->z);
fixed_t bx = FixedMul(rotVec->x,ys+zs);
fixed_t by = FixedMul(rotVec->y,xs+zs);
fixed_t bz = FixedMul(rotVec->z,xs+ys);
fixed_t cx = FixedMul(axisVec->x,vy+wz);
fixed_t cy = FixedMul(axisVec->y,ux+wz);
fixed_t cz = FixedMul(axisVec->z,ux+vy);
fixed_t dx = FixedMul(bx-cx, ca);
fixed_t dy = FixedMul(by-cy, ca);
fixed_t dz = FixedMul(bz-cz, ca);
fixed_t ex = FixedMul(vz-wy, sa);
fixed_t ey = FixedMul(wx-uz, sa);
fixed_t ez = FixedMul(uy-vx, sa);
rotVec->x = ax+dx+ex;
rotVec->y = ay+dy+ey;
rotVec->z = az+dz+ez;
}
void FM_Rotate(fmatrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z) void FM_Rotate(fmatrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
{ {
#define M(row,col) dest->m[row * 4 + col] #define M(row,col) dest->m[row * 4 + col]

View file

@ -1,4 +1,4 @@
// Emacs style mode select -*- C++ -*- // Emacs style mode select -*- C++ -*-
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Copyright(C) 2004 Stephen McGranahan // Copyright(C) 2004 Stephen McGranahan
@ -7,12 +7,12 @@
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or // the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@ -114,6 +114,8 @@ float M_VectorYaw(v3float_t v);
float M_VectorPitch(v3float_t v); float M_VectorPitch(v3float_t v);
angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byte AngleAxis, float Rate); angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byte AngleAxis, float Rate);
void M_VecRotate(v3fixed_t *rotVec, const v3fixed_t *axisVec, const angle_t angle);
#endif #endif

View file

@ -1239,7 +1239,11 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
} }
else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale) else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale)
&& abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale) && abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale)
&& (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING))) && (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING))
#ifdef ESLOPE
&& !(player->mo->standingslope && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
#endif
)
{ {
// if in a walking frame, stop moving // if in a walking frame, stop moving
if (player->panim == PA_WALK) if (player->panim == PA_WALK)
@ -1383,6 +1387,11 @@ void P_XYMovement(mobj_t *mo)
fixed_t xmove, ymove; fixed_t xmove, ymove;
fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
boolean moved; boolean moved;
#ifdef ESLOPE
pslope_t *oldslope = NULL;
v3fixed_t slopemom;
fixed_t predictedz;
#endif
I_Assert(mo != NULL); I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo)); I_Assert(!P_MobjWasRemoved(mo));
@ -1414,6 +1423,29 @@ void P_XYMovement(mobj_t *mo)
oldx = mo->x; oldx = mo->x;
oldy = mo->y; oldy = mo->y;
#ifdef ESLOPE
// adjust various things based on slope
if (mo->standingslope) {
if (!P_IsObjectOnGround(mo)) { // We fell off at some point? Do the twisty thing!
P_SlopeLaunch(mo);
xmove = mo->momx;
ymove = mo->momy;
} else { // Still on the ground.
slopemom.x = xmove;
slopemom.y = ymove;
slopemom.z = 0;
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
xmove = slopemom.x;
ymove = slopemom.y;
predictedz = mo->z + slopemom.z; // We'll use this later...
oldslope = mo->standingslope;
}
}
#endif
// Pushables can break some blocks // Pushables can break some blocks
if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE)
P_PushableCheckBustables(mo); P_PushableCheckBustables(mo);
@ -1534,6 +1566,29 @@ void P_XYMovement(mobj_t *mo)
if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;; if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;;
return; return;
#ifdef ESLOPE
if (moved && oldslope) { // Check to see if we ran off
if (oldslope != mo->standingslope) { // First, compare different slopes
// Start by quantizing momentum on this slope
v3fixed_t test;
test.x = mo->momx;
test.y = mo->momy;
test.z = 0;
if (mo->standingslope) // Don't fuss with the rotation if we don't HAVE a slope
P_QuantizeMomentumToSlope(&test, mo->standingslope);
// Now compare the Zs of the different quantizations
if (slopemom.z - test.z > 2*FRACUNIT) { // Allow for a bit of sticking - this value can be adjusted later
mo->standingslope = oldslope;
P_SlopeLaunch(mo);
}
} else if (predictedz-mo->z > 2*FRACUNIT) { // Now check if we were supposed to stick to this slope
mo->standingslope = oldslope;
P_SlopeLaunch(mo);
}
}
#endif
// Check the gravity status. // Check the gravity status.
P_CheckGravity(mo, false); P_CheckGravity(mo, false);
@ -1819,6 +1874,11 @@ static boolean P_ZMovement(mobj_t *mo)
I_Assert(mo != NULL); I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo)); I_Assert(!P_MobjWasRemoved(mo));
#ifdef ESLOPE
if (mo->standingslope && !P_IsObjectOnGround(mo))
P_SlopeLaunch(mo);
#endif
// Intercept the stupid 'fall through 3dfloors' bug // Intercept the stupid 'fall through 3dfloors' bug
if (mo->subsector->sector->ffloors) if (mo->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0); P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
@ -2231,6 +2291,11 @@ static void P_PlayerZMovement(mobj_t *mo)
if (!mo->player) if (!mo->player)
return; return;
#ifdef ESLOPE
if (mo->standingslope && !P_IsObjectOnGround(mo))
P_SlopeLaunch(mo);
#endif
// Intercept the stupid 'fall through 3dfloors' bug // Intercept the stupid 'fall through 3dfloors' bug
if (mo->subsector->sector->ffloors) if (mo->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0); P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
@ -3183,6 +3248,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
P_MobjCheckWater(mobj); P_MobjCheckWater(mobj);
#ifdef ESLOPE
P_ButteredSlope(mobj);
#endif
// momentum movement // momentum movement
mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;

View file

@ -768,6 +768,69 @@ float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori,
(point->z - pori->z) * pnormal->z; (point->z - pori->z) * pnormal->z;
} }
//
// P_QuantizeMomentumToSlope
//
// When given a vector, rotates it and aligns it to a slope
void P_QuantizeMomentumToSlope(v3fixed_t *momentum, pslope_t *slope)
{
v3fixed_t axis;
axis.x = -slope->d.y;
axis.y = slope->d.x;
axis.z = 0;
M_VecRotate(momentum, &axis, slope->zangle);
}
//
// P_SlopeLaunch
//
// Handles slope ejection for objects
void P_SlopeLaunch(mobj_t *mo)
{
// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
// vertical launch given from slopes while increasing the horizontal launch
// given. Good for SRB2's gravity and horizontal speeds.
v3fixed_t slopemom;
slopemom.x = mo->momx;
slopemom.y = mo->momy;
slopemom.z = mo->momz*2;
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
mo->momx = slopemom.x;
mo->momy = slopemom.y;
mo->momz = slopemom.z/2;
CONS_Printf("Launched off of slope.\n");
mo->standingslope = NULL;
}
// https://yourlogicalfallacyis.com/slippery-slope
// Handles sliding down slopes, like if they were made of butter :)
void P_ButteredSlope(mobj_t *mo)
{
fixed_t thrust;
if (!mo->standingslope)
return;
if (abs(mo->standingslope->zdelta) < FRACUNIT/2)
return; // Don't apply physics to slopes that aren't steep enough
thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1);
if (!(mo->player && (mo->player->pflags & PF_SPINNING))) {
if (mo->momx || mo->momy) // Slightly increase thrust based on the object's speed parallel to the slope direction
thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/4);
// This solves the issue of being able to zigzag up steep slopes
}
// Multiply by gravity
thrust = FixedMul(thrust, FRACUNIT/2); // TODO actually get this
P_Thrust(mo, mo->standingslope->xydirection, thrust);
}
// EOF // EOF
#endif // #ifdef ESLOPE #endif // #ifdef ESLOPE

View file

@ -76,6 +76,11 @@ float P_GetZAtf(pslope_t *slope, float x, float y);
float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori, float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori,
const v3float_t *pnormal); const v3float_t *pnormal);
// Lots of physics-based bullshit
void P_QuantizeMomentumToSlope(v3fixed_t *momentum, pslope_t *slope);
void P_SlopeLaunch(mobj_t *mo);
void P_ButteredSlope(mobj_t *mo);
#endif #endif
// EOF // EOF