mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Loops: correct origin point over duration of loop
- Players moving into a gate with a lot of momentum would offset the origin point from its intended position - Find intersection of player movement and gate - Correct origin point between loop entry and exit by interpolating the difference between player position on entry and intersection point
This commit is contained in:
parent
b9615d7225
commit
428106c014
5 changed files with 109 additions and 11 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
25
src/p_loop.c
25
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)
|
||||
|
|
@ -98,6 +94,7 @@ boolean P_PlayerOrbit(player_t *player)
|
|||
sonicloopvars_t *s = &player->loop;
|
||||
|
||||
angle_t pitch;
|
||||
angle_t pitch_normal;
|
||||
|
||||
fixed_t xy, z;
|
||||
fixed_t xs, ys;
|
||||
|
|
@ -125,15 +122,25 @@ 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)));
|
||||
|
||||
th = get_shift_curve(s);
|
||||
// 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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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