mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'fuck-you-loops' into 'master'
Fix inaccuracies on loop exit + smoother entry See merge request KartKrew/Kart!1552
This commit is contained in:
commit
2e1983dd7f
10 changed files with 167 additions and 53 deletions
|
|
@ -471,6 +471,7 @@ typedef struct {
|
|||
fixed_t revolution, min_revolution, max_revolution;
|
||||
angle_t yaw;
|
||||
vector3_t origin;
|
||||
vector2_t origin_shift;
|
||||
vector2_t shift;
|
||||
boolean flip;
|
||||
} sonicloopvars_t;
|
||||
|
|
|
|||
44
src/k_kart.c
44
src/k_kart.c
|
|
@ -7847,6 +7847,15 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->mo->sprzoff += player->cameraOffset;
|
||||
}
|
||||
|
||||
if (player->loop.radius)
|
||||
{
|
||||
// Offset sprite Z position so wheels touch top of
|
||||
// hitbox when rotated 180 degrees.
|
||||
// TODO: this should be generalized for pitch/roll
|
||||
angle_t pitch = FixedAngle(player->loop.revolution * 360) / 2;
|
||||
player->mo->sprzoff += FixedMul(player->mo->height, FSIN(pitch));
|
||||
}
|
||||
|
||||
K_UpdateOffroad(player);
|
||||
K_UpdateDraft(player);
|
||||
K_UpdateEngineSounds(player); // Thanks, VAda!
|
||||
|
|
@ -10502,21 +10511,7 @@ static void K_KartSpindash(player_t *player)
|
|||
P_InstaThrust(player->mo, player->mo->angle, thrust);
|
||||
}
|
||||
|
||||
if (!player->tiregrease)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
mobj_t *grease;
|
||||
grease = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_TIREGREASE);
|
||||
P_SetTarget(&grease->target, player->mo);
|
||||
grease->angle = K_MomentumAngle(player->mo);
|
||||
grease->extravalue1 = i;
|
||||
K_ReduceVFX(grease, player);
|
||||
}
|
||||
}
|
||||
|
||||
player->tiregrease = 2*TICRATE;
|
||||
K_SetTireGrease(player, 2*TICRATE);
|
||||
|
||||
player->spindash = 0;
|
||||
S_ReducedVFXSound(player->mo, sfx_s23c, player);
|
||||
|
|
@ -12470,4 +12465,23 @@ boolean K_Cooperative(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
void K_SetTireGrease(player_t *player, tic_t tics)
|
||||
{
|
||||
if (!player->tiregrease)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
mobj_t *grease;
|
||||
grease = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_TIREGREASE);
|
||||
P_SetTarget(&grease->target, player->mo);
|
||||
grease->angle = K_MomentumAngle(player->mo);
|
||||
grease->extravalue1 = i;
|
||||
K_ReduceVFX(grease, player);
|
||||
}
|
||||
}
|
||||
|
||||
player->tiregrease = tics;
|
||||
}
|
||||
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -235,6 +235,8 @@ boolean K_Cooperative(void);
|
|||
// lat: used for when the player is in some weird state where it wouldn't be wise for it to be overwritten by another object that does similarly wacky shit.
|
||||
boolean K_isPlayerInSpecialState(player_t *p);
|
||||
|
||||
void K_SetTireGrease(player_t *player, tic_t tics);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
ufo.c
|
||||
monitor.c
|
||||
item-spot.c
|
||||
loops.c
|
||||
loops.cpp
|
||||
drop-target.c
|
||||
ring-shooter.c
|
||||
audience.c
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
/// \file loop-endpoint.c
|
||||
/// \brief Sonic loops, start and end points
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../k_kart.h"
|
||||
#include "../taglist.h"
|
||||
|
|
@ -149,6 +151,81 @@ get_binary_direction
|
|||
}
|
||||
}
|
||||
|
||||
static std::optional<vector2_t>
|
||||
intersect
|
||||
( const mobj_t * anchor,
|
||||
const mobj_t * toucher)
|
||||
{
|
||||
struct Line
|
||||
{
|
||||
angle_t a;
|
||||
vector2_t o;
|
||||
|
||||
angle_t k = AbsAngle(a);
|
||||
|
||||
Line(vector2_t o_, angle_t a_) : a(a_), o(o_) {}
|
||||
|
||||
bool vertical() const { return k == ANGLE_90; }
|
||||
|
||||
fixed_t m() const
|
||||
{
|
||||
// tangent table is offset 90 degrees
|
||||
return FTAN(a - ANGLE_90);
|
||||
}
|
||||
|
||||
fixed_t b() const
|
||||
{
|
||||
return o.y - FixedMul(o.x, m());
|
||||
}
|
||||
|
||||
fixed_t y(fixed_t x) const
|
||||
{
|
||||
return FixedMul(m(), x) + b();
|
||||
}
|
||||
};
|
||||
|
||||
if (toucher->momx == 0 && toucher->momy == 0)
|
||||
{
|
||||
// undefined angle
|
||||
return {};
|
||||
}
|
||||
|
||||
Line a({toucher->x, toucher->y},
|
||||
R_PointToAngle2(0, 0, toucher->momx, toucher->momy));
|
||||
|
||||
Line b({anchor->x, anchor->y}, anchor->angle + ANGLE_90);
|
||||
|
||||
if (a.k == b.k)
|
||||
{
|
||||
// parallel lines do not intersect
|
||||
return {};
|
||||
}
|
||||
|
||||
vector2_t v;
|
||||
|
||||
auto v_intersect = [&v](Line &a, Line &b)
|
||||
{
|
||||
if (a.vertical())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
v.x = b.o.x;
|
||||
v.y = a.y(v.x);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!v_intersect(a, b) && !v_intersect(b, a))
|
||||
{
|
||||
// untested!
|
||||
v.x = FixedDiv(a.b() - b.b(), b.m() - a.m());
|
||||
v.y = a.y(v.x);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
mobj_t *
|
||||
Obj_FindLoopCenter (const mtag_t tag)
|
||||
{
|
||||
|
|
@ -226,8 +303,8 @@ Obj_LoopEndpointCollide
|
|||
fixed_t radius;
|
||||
|
||||
/* predict movement for a smooth transition */
|
||||
const fixed_t px = toucher->x + toucher->momx;
|
||||
const fixed_t py = toucher->y + toucher->momy;
|
||||
const fixed_t px = toucher->x + 2 * toucher->momx;
|
||||
const fixed_t py = toucher->y + 2 * toucher->momy;
|
||||
|
||||
SINT8 flip;
|
||||
|
||||
|
|
@ -251,6 +328,11 @@ Obj_LoopEndpointCollide
|
|||
if (!P_MobjWasRemoved(anchor_other(anchor)))
|
||||
{
|
||||
set_shiftxy(player, anchor);
|
||||
|
||||
vector2_t i = intersect(anchor, toucher)
|
||||
.value_or(vector2_t {px, py});
|
||||
|
||||
s->origin_shift = {i.x - px, i.y - py};
|
||||
}
|
||||
|
||||
flip = get_binary_direction(pitch, toucher);
|
||||
|
|
@ -276,4 +358,7 @@ Obj_LoopEndpointCollide
|
|||
/* cancel the effects of K_Squish */
|
||||
toucher->spritexscale = FRACUNIT;
|
||||
toucher->spriteyscale = FRACUNIT;
|
||||
|
||||
toucher->momx = 0;
|
||||
toucher->momy = 0;
|
||||
}
|
||||
44
src/p_loop.c
44
src/p_loop.c
|
|
@ -24,15 +24,11 @@ get_pitch (fixed_t revolution)
|
|||
}
|
||||
|
||||
static inline fixed_t
|
||||
get_shift_curve (const sonicloopvars_t *s)
|
||||
normal_revolution (const sonicloopvars_t *s)
|
||||
{
|
||||
const angle_t th = get_pitch(FixedDiv(
|
||||
s->revolution - s->min_revolution,
|
||||
s->max_revolution - s->min_revolution));
|
||||
|
||||
// XY shift is transformed on wave scale; less movement
|
||||
// at start and end of rotation, more halfway.
|
||||
return FSIN((th / 2) - ANGLE_90);
|
||||
return FixedDiv(
|
||||
s->revolution - s->min_revolution,
|
||||
s->max_revolution - s->min_revolution);
|
||||
}
|
||||
|
||||
void P_HaltPlayerOrbit(player_t *player)
|
||||
|
|
@ -88,7 +84,7 @@ void P_ExitPlayerOrbit(player_t *player)
|
|||
}
|
||||
|
||||
// tiregrease gives less friction, extends momentum
|
||||
player->tiregrease = TICRATE;
|
||||
K_SetTireGrease(player, 3*TICRATE);
|
||||
|
||||
P_HaltPlayerOrbit(player);
|
||||
}
|
||||
|
|
@ -98,8 +94,9 @@ boolean P_PlayerOrbit(player_t *player)
|
|||
sonicloopvars_t *s = &player->loop;
|
||||
|
||||
angle_t pitch;
|
||||
angle_t pitch_normal;
|
||||
|
||||
fixed_t xy, z;
|
||||
fixed_t r, xy, z;
|
||||
fixed_t xs, ys;
|
||||
|
||||
fixed_t step, th, left;
|
||||
|
|
@ -125,15 +122,29 @@ boolean P_PlayerOrbit(player_t *player)
|
|||
}
|
||||
|
||||
pitch = get_pitch(s->revolution);
|
||||
pitch_normal = get_pitch(normal_revolution(s) / 2);
|
||||
|
||||
xy = FixedMul(abs(s->radius), FSIN(pitch));
|
||||
z = FixedMul(abs(s->radius), -(FCOS(pitch)));
|
||||
r = abs(s->radius) -
|
||||
FixedMul(player->mo->radius, abs(FSIN(pitch)));
|
||||
|
||||
th = get_shift_curve(s);
|
||||
xy = FixedMul(r, FSIN(pitch));
|
||||
|
||||
z = FixedMul(abs(s->radius), -(FCOS(pitch))) -
|
||||
FixedMul(player->mo->height, FSIN(pitch / 2));
|
||||
|
||||
// XY shift is transformed on wave scale; less movement
|
||||
// at start and end of rotation, more halfway.
|
||||
th = FSIN(pitch_normal - ANGLE_90);
|
||||
|
||||
xs = FixedMul(s->shift.x, th);
|
||||
ys = FixedMul(s->shift.y, th);
|
||||
|
||||
// Interpolate 0-1 over entire rotation.
|
||||
th = FSIN(pitch_normal / 2);
|
||||
|
||||
xs += FixedMul(s->origin_shift.x, th);
|
||||
ys += FixedMul(s->origin_shift.y, th);
|
||||
|
||||
xs += FixedMul(xy, FCOS(s->yaw));
|
||||
ys += FixedMul(xy, FSIN(s->yaw));
|
||||
|
||||
|
|
@ -153,13 +164,18 @@ boolean P_PlayerOrbit(player_t *player)
|
|||
|
||||
left = (s->max_revolution - s->revolution);
|
||||
|
||||
if (abs(left) < abs(step))
|
||||
if (left == 0)
|
||||
{
|
||||
P_ExitPlayerOrbit(player);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (abs(left) < abs(step))
|
||||
{
|
||||
step = left;
|
||||
}
|
||||
|
||||
// If player slows down by too much, throw them out of
|
||||
// the loop in a tumble.
|
||||
if (player->speed < player->mo->scale)
|
||||
|
|
|
|||
20
src/p_map.c
20
src/p_map.c
|
|
@ -323,25 +323,7 @@ P_DoSpringEx
|
|||
object->player->springstars = max(abs(vertispeed), horizspeed) / FRACUNIT / 2;
|
||||
object->player->springcolor = starcolor;
|
||||
|
||||
// Less friction when hitting springs
|
||||
if (!object->player->tiregrease)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
mobj_t *grease;
|
||||
grease = P_SpawnMobj(object->x, object->y, object->z, MT_TIREGREASE);
|
||||
P_SetTarget(&grease->target, object);
|
||||
grease->angle = K_MomentumAngle(object);
|
||||
grease->extravalue1 = i;
|
||||
K_ReduceVFX(grease, object->player);
|
||||
}
|
||||
}
|
||||
|
||||
if (object->player->tiregrease < greasetics)
|
||||
{
|
||||
object->player->tiregrease = greasetics;
|
||||
}
|
||||
K_SetTireGrease(object->player, max(object->player->tiregrease, greasetics));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -674,6 +674,8 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEFIXED(save->p, players[i].loop.origin.x);
|
||||
WRITEFIXED(save->p, players[i].loop.origin.y);
|
||||
WRITEFIXED(save->p, players[i].loop.origin.z);
|
||||
WRITEFIXED(save->p, players[i].loop.origin_shift.x);
|
||||
WRITEFIXED(save->p, players[i].loop.origin_shift.y);
|
||||
WRITEFIXED(save->p, players[i].loop.shift.x);
|
||||
WRITEFIXED(save->p, players[i].loop.shift.y);
|
||||
WRITEUINT8(save->p, players[i].loop.flip);
|
||||
|
|
@ -1196,6 +1198,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].loop.origin.x = READFIXED(save->p);
|
||||
players[i].loop.origin.y = READFIXED(save->p);
|
||||
players[i].loop.origin.z = READFIXED(save->p);
|
||||
players[i].loop.origin_shift.x = READFIXED(save->p);
|
||||
players[i].loop.origin_shift.y = READFIXED(save->p);
|
||||
players[i].loop.shift.x = READFIXED(save->p);
|
||||
players[i].loop.shift.y = READFIXED(save->p);
|
||||
players[i].loop.flip = READUINT8(save->p);
|
||||
|
|
|
|||
13
src/p_user.c
13
src/p_user.c
|
|
@ -3289,7 +3289,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]);
|
||||
}
|
||||
|
||||
speed = P_AproxDistance(P_AproxDistance(mo->momx, mo->momy), mo->momz / 16);
|
||||
if (player->loop.radius)
|
||||
{
|
||||
speed = player->speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = P_AproxDistance(P_AproxDistance(mo->momx, mo->momy), mo->momz / 16);
|
||||
}
|
||||
|
||||
lag = FRACUNIT - ((FixedDiv(speed, speedthreshold) - FRACUNIT) * 2);
|
||||
|
||||
if (lag > FRACUNIT)
|
||||
|
|
@ -4265,7 +4273,8 @@ void P_PlayerThink(player_t *player)
|
|||
else if (player->loop.radius != 0)
|
||||
{
|
||||
P_PlayerOrbit(player);
|
||||
player->rmomx = player->rmomy = 0;
|
||||
player->rmomx = player->mo->momx;
|
||||
player->rmomy = player->mo->momy;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z);
|
|||
// FSIN(ANGLE_90) = FRACUNIT
|
||||
#define FSIN(n) FINESINE(ANGLETOFINE(n))
|
||||
#define FCOS(n) FINECOSINE(ANGLETOFINE(n))
|
||||
#define FTAN(n) FINETANGENT(((n) >> ANGLETOFINESHIFT) & ((FINEANGLES / 2) - 1))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue