From 4bdc05824c7bd342c08be52690d058b2604ae895 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Aug 2023 03:24:22 -0700 Subject: [PATCH] Add Obj_BeginEmeraldOrbit, seamless transition into orbit --- src/k_objects.h | 1 + src/objects/emerald.c | 94 ++++++++++++++++++++++++++++++++++--------- src/objects/ufo.c | 2 +- 3 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/k_objects.h b/src/k_objects.h index 8066e7078..513f88fdb 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -207,6 +207,7 @@ void Obj_SneakerPanelCollide(mobj_t *pad, mobj_t *mo); /* Emerald */ void Obj_SpawnEmeraldSparks(mobj_t *source); void Obj_EmeraldThink(mobj_t *emerald); +void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time); #ifdef __cplusplus } // extern "C" diff --git a/src/objects/emerald.c b/src/objects/emerald.c index 40524cd12..6ef557b12 100644 --- a/src/objects/emerald.c +++ b/src/objects/emerald.c @@ -3,8 +3,16 @@ #include "../info.h" #include "../m_random.h" #include "../p_local.h" +#include "../r_main.h" #include "../tables.h" +#define emerald_type(o) ((o)->extravalue1) +#define emerald_anim_start(o) ((o)->movedir) +#define emerald_revolution_time(o) ((o)->threshold) +#define emerald_start_radius(o) ((o)->movecount) +#define emerald_target_radius(o) ((o)->extravalue2) +#define emerald_z_shift(o) ((o)->reactiontime) + void Obj_SpawnEmeraldSparks(mobj_t *mobj) { if (leveltime % 3 != 0) @@ -25,31 +33,64 @@ void Obj_SpawnEmeraldSparks(mobj_t *mobj) sparkle->sprzoff = mobj->sprzoff; } +static INT32 get_elapsed(mobj_t *emerald) +{ + return leveltime - min((tic_t)emerald_anim_start(emerald), leveltime); +} + +static INT32 get_revolve_time(mobj_t *emerald) +{ + return max(1, emerald_revolution_time(emerald)); +} + +static fixed_t get_suck_factor(mobj_t *emerald) +{ + const INT32 suck_time = get_revolve_time(emerald) * 2; + + return (min(get_elapsed(emerald), suck_time) * FRACUNIT) / suck_time; +} + +static fixed_t get_current_radius(mobj_t *emerald) +{ + fixed_t s = emerald_start_radius(emerald); + fixed_t t = emerald_target_radius(emerald); + + return s + FixedMul(t - s, get_suck_factor(emerald)); +} + +static fixed_t get_bob(mobj_t *emerald) +{ + angle_t phase = get_elapsed(emerald) * ((ANGLE_MAX / get_revolve_time(emerald)) / 2); + + return FixedMul(30 * mapobjectscale, FSIN(emerald->angle + phase)); +} + +static fixed_t center_of(mobj_t *mobj) +{ + return mobj->z + (mobj->height / 2); +} + +static fixed_t get_target_z(mobj_t *emerald) +{ + fixed_t shift = FixedMul(emerald_z_shift(emerald), FRACUNIT - get_suck_factor(emerald)); + + return center_of(emerald->target) + get_bob(emerald) + shift; +} + static void Obj_EmeraldOrbitPlayer(mobj_t *emerald) { - const int kOrbitTics = 64; - const int kPhaseTics = 128; - - const fixed_t orbit_radius = 100 * mapobjectscale; - const fixed_t orbit_height = 30 * mapobjectscale; - - mobj_t *targ = emerald->target; - - angle_t a = emerald->angle; - - fixed_t x = FixedMul(orbit_radius, FCOS(a)); - fixed_t y = FixedMul(orbit_radius, FSIN(a)); - - angle_t phase = (ANGLE_MAX / kPhaseTics) * (leveltime % kPhaseTics); + fixed_t r = get_current_radius(emerald); + fixed_t x = FixedMul(r, FCOS(emerald->angle)); + fixed_t y = FixedMul(r, FSIN(emerald->angle)); P_MoveOrigin( emerald, - targ->x + x, - targ->y + y, - targ->z + targ->height + FixedMul(orbit_height, FSIN(a + phase)) + emerald->target->x + x, + emerald->target->y + y, + get_target_z(emerald) ); - emerald->angle += ANGLE_MAX / kOrbitTics; + emerald->angle += ANGLE_MAX / get_revolve_time(emerald); } void Obj_EmeraldThink(mobj_t *emerald) @@ -84,3 +125,20 @@ void Obj_EmeraldThink(mobj_t *emerald) K_BattleOvertimeKiller(emerald); } + +void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time) +{ + P_SetTarget(&emerald->target, target); + + emerald_anim_start(emerald) = leveltime; + emerald_revolution_time(emerald) = revolution_time; + + emerald_start_radius(emerald) = R_PointToDist2(target->x, target->y, emerald->x, emerald->y); + emerald_target_radius(emerald) = radius; + + emerald->angle = R_PointToAngle2(target->x, target->y, emerald->x, emerald->y); + emerald_z_shift(emerald) = emerald->z - get_target_z(emerald); + + emerald->flags |= MF_NOGRAVITY | MF_NOCLIP | MF_NOCLIPTHING | MF_NOCLIPHEIGHT; + emerald->shadowscale = 0; +} diff --git a/src/objects/ufo.c b/src/objects/ufo.c index f8e15c459..0ed90df50 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -883,7 +883,7 @@ boolean Obj_UFOEmeraldCollect(mobj_t *ufo, mobj_t *toucher) const int kScaleTics = 16; // Emerald will now orbit the player - P_SetTarget(&emerald->target, toucher); + Obj_BeginEmeraldOrbit(emerald, toucher, 100 * mapobjectscale, 64); // Scale down because the emerald is huge // Super Emerald needs to be scaled down further