From 83051728f0809d066eea4593e27a6efbd05d5ea5 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 21 Feb 2023 18:45:22 -0800 Subject: [PATCH] Move capsule target code out of k_hud.c, to k_hud_track.cpp --- src/CMakeLists.txt | 1 + src/k_hud.c | 295 +------------------------------------------- src/k_hud.h | 5 + src/k_hud_track.cpp | 289 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+), 290 deletions(-) create mode 100644 src/k_hud_track.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ce816523e..ac592f89d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -121,6 +121,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 k_grandprix.c k_boss.c k_hud.c + k_hud_track.cpp k_menufunc.c k_menudraw.c k_terrain.c diff --git a/src/k_hud.c b/src/k_hud.c index bdc14e596..5fbc5b1a3 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -174,10 +174,10 @@ static patch_t *kp_bossret[4]; static patch_t *kp_trickcool[2]; -static patch_t *kp_capsuletarget_arrow[2][2]; -static patch_t *kp_capsuletarget_icon[2]; -static patch_t *kp_capsuletarget_far[2]; -static patch_t *kp_capsuletarget_near[8]; +patch_t *kp_capsuletarget_arrow[2][2]; +patch_t *kp_capsuletarget_icon[2]; +patch_t *kp_capsuletarget_far[2]; +patch_t *kp_capsuletarget_near[8]; void K_LoadKartHUDGraphics(void) { @@ -3175,217 +3175,6 @@ static void K_DrawWeakSpot(weakspotdraw_t *ws) V_DrawFixedPatch(ws->x, ws->y, FRACUNIT, 0, kp_bossret[j+1], colormap); } -typedef struct capsuletracking_s -{ - mobj_t *mobj; - vector3_t point; - fixed_t camDist; -} capsuletracking_t; - -static void K_DrawCapsuleTracking(capsuletracking_t *caps) -{ - trackingResult_t result = {0}; - INT32 timer = 0; - - K_ObjectTracking(&result, &caps->point, false); - - if (result.onScreen == false) - { - // Off-screen, draw alongside the borders of the screen. - // Probably the most complicated thing. - - INT32 scrVal = 240; - vector2_t screenSize = {0}; - - INT32 borderSize = 7; - vector2_t borderWin = {0}; - vector2_t borderDir = {0}; - fixed_t borderLen = FRACUNIT; - - vector2_t arrowDir = {0}; - - vector2_t arrowPos = {0}; - patch_t *arrowPatch = NULL; - INT32 arrowFlags = 0; - - vector2_t capsulePos = {0}; - patch_t *capsulePatch = NULL; - - timer = (leveltime / 3); - - screenSize.x = vid.width / vid.dupx; - screenSize.y = vid.height / vid.dupy; - - if (r_splitscreen >= 2) - { - // Half-wide screens - screenSize.x >>= 1; - borderSize >>= 1; - } - - if (r_splitscreen >= 1) - { - // Half-tall screens - screenSize.y >>= 1; - } - - scrVal = max(screenSize.x, screenSize.y) - 80; - - borderWin.x = screenSize.x - borderSize; - borderWin.y = screenSize.y - borderSize; - - arrowDir.x = 0; - arrowDir.y = P_MobjFlip(caps->mobj) * FRACUNIT; - - // Simply pointing towards the result doesn't work, so inaccurate hack... - borderDir.x = FixedMul( - FixedMul( - FINESINE((-result.angle >> ANGLETOFINESHIFT) & FINEMASK), - FINECOSINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK) - ), - result.fov - ); - - borderDir.y = FixedMul( - FINESINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK), - result.fov - ); - - borderLen = R_PointToDist2(0, 0, borderDir.x, borderDir.y); - - if (borderLen > 0) - { - borderDir.x = FixedDiv(borderDir.x, borderLen); - borderDir.y = FixedDiv(borderDir.y, borderLen); - } - else - { - // Eh just put it at the bottom. - borderDir.x = 0; - borderDir.y = FRACUNIT; - } - - capsulePatch = kp_capsuletarget_icon[timer & 1]; - - if (abs(borderDir.x) > abs(borderDir.y)) - { - // Horizontal arrow - arrowPatch = kp_capsuletarget_arrow[1][timer & 1]; - arrowDir.y = 0; - - if (borderDir.x < 0) - { - // LEFT - arrowDir.x = -FRACUNIT; - } - else - { - // RIGHT - arrowDir.x = FRACUNIT; - } - } - else - { - // Vertical arrow - arrowPatch = kp_capsuletarget_arrow[0][timer & 1]; - arrowDir.x = 0; - - if (borderDir.y < 0) - { - // UP - arrowDir.y = -FRACUNIT; - } - else - { - // DOWN - arrowDir.y = FRACUNIT; - } - } - - arrowPos.x = (screenSize.x >> 1) + FixedMul(scrVal, borderDir.x); - arrowPos.y = (screenSize.y >> 1) + FixedMul(scrVal, borderDir.y); - - arrowPos.x = min(max(arrowPos.x, borderSize), borderWin.x) * FRACUNIT; - arrowPos.y = min(max(arrowPos.y, borderSize), borderWin.y) * FRACUNIT; - - capsulePos.x = arrowPos.x - (arrowDir.x * 12); - capsulePos.y = arrowPos.y - (arrowDir.y * 12); - - arrowPos.x -= (arrowPatch->width << FRACBITS) >> 1; - arrowPos.y -= (arrowPatch->height << FRACBITS) >> 1; - - capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1; - capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1; - - if (arrowDir.x < 0) - { - arrowPos.x += arrowPatch->width << FRACBITS; - arrowFlags |= V_FLIP; - } - - if (arrowDir.y < 0) - { - arrowPos.y += arrowPatch->height << FRACBITS; - arrowFlags |= V_VFLIP; - } - - V_DrawFixedPatch( - capsulePos.x, capsulePos.y, - FRACUNIT, - V_SPLITSCREEN, - capsulePatch, NULL - ); - - V_DrawFixedPatch( - arrowPos.x, arrowPos.y, - FRACUNIT, - V_SPLITSCREEN | arrowFlags, - arrowPatch, NULL - ); - } - else - { - // Draw simple overlay. - const fixed_t farDistance = 1280*mapobjectscale; - boolean useNear = (caps->camDist < farDistance); - - patch_t *capsulePatch = NULL; - vector2_t capsulePos = {0}; - - boolean visible = P_CheckSight(stplyr->mo, caps->mobj); - - if (visible == false && (leveltime & 1)) - { - // Flicker when not visible. - return; - } - - capsulePos.x = result.x; - capsulePos.y = result.y; - - if (useNear == true) - { - timer = (leveltime / 2); - capsulePatch = kp_capsuletarget_near[timer % 8]; - } - else - { - timer = (leveltime / 3); - capsulePatch = kp_capsuletarget_far[timer & 1]; - } - - capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1; - capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1; - - V_DrawFixedPatch( - capsulePos.x, capsulePos.y, - FRACUNIT, - V_SPLITSCREEN, - capsulePatch, NULL - ); - } -} - static void K_drawKartNameTags(void) { const fixed_t maxdistance = 8192*mapobjectscale; @@ -3487,81 +3276,7 @@ static void K_drawKartNameTags(void) if (battlecapsules == true) { -#define MAX_CAPSULE_HUD 32 - capsuletracking_t capsuleList[MAX_CAPSULE_HUD]; - size_t capsuleListLen = 0; - - mobj_t *mobj = NULL; - mobj_t *next = NULL; - - for (mobj = trackercap; mobj; mobj = next) - { - capsuletracking_t *caps = NULL; - - next = mobj->itnext; - - if (mobj->health <= 0) - { - continue; - } - - if (mobj->type != MT_BATTLECAPSULE) - { - continue; - } - - caps = &capsuleList[capsuleListLen]; - - caps->mobj = mobj; - caps->point.x = R_InterpolateFixed(mobj->old_x, mobj->x); - caps->point.y = R_InterpolateFixed(mobj->old_y, mobj->y); - caps->point.z = R_InterpolateFixed(mobj->old_z, mobj->z); - caps->point.z += (mobj->height >> 1); - caps->camDist = R_PointToDist2(c.x, c.y, caps->point.x, caps->point.y); - - capsuleListLen++; - - if (capsuleListLen >= MAX_CAPSULE_HUD) - { - break; - } - } - - if (capsuleListLen > 0) - { - // Sort by distance from camera. - if (capsuleListLen > 1) - { - for (i = 0; i < capsuleListLen-1; i++) - { - size_t swap = i; - - for (j = i + 1; j < capsuleListLen; j++) - { - capsuletracking_t *cj = &capsuleList[j]; - capsuletracking_t *cSwap = &capsuleList[swap]; - - if (cj->camDist > cSwap->camDist) - { - swap = j; - } - } - - if (swap != i) - { - capsuletracking_t temp = capsuleList[swap]; - capsuleList[swap] = capsuleList[i]; - capsuleList[i] = temp; - } - } - } - - for (i = 0; i < capsuleListLen; i++) - { - K_DrawCapsuleTracking(&capsuleList[i]); - } - } -#undef MAX_CAPSULE_HUD + K_drawTargetHUD(&c, stplyr); } for (i = 0; i < MAXPLAYERS; i++) diff --git a/src/k_hud.h b/src/k_hud.h index 9b783f710..7d2b5354a 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -44,8 +44,13 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol); void K_DrawMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, UINT16 map, UINT8 *colormap); void K_DrawLikeMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, patch_t *patch, UINT8 *colormap); +void K_drawTargetHUD(const vector3_t *origin, player_t *player); extern patch_t *kp_facehighlight[8]; +extern patch_t *kp_capsuletarget_arrow[2][2]; +extern patch_t *kp_capsuletarget_icon[2]; +extern patch_t *kp_capsuletarget_far[2]; +extern patch_t *kp_capsuletarget_near[8]; #ifdef __cplusplus } // extern "C" diff --git a/src/k_hud_track.cpp b/src/k_hud_track.cpp new file mode 100644 index 000000000..8b6c782d5 --- /dev/null +++ b/src/k_hud_track.cpp @@ -0,0 +1,289 @@ +#include +#include + +#include "k_hud.h" +#include "m_fixed.h" +#include "p_local.h" +#include "p_mobj.h" +#include "r_fps.h" +#include "r_main.h" +#include "v_video.h" + +namespace +{ + +struct capsuletracking_t +{ + mobj_t* mobj; + vector3_t point; + fixed_t camDist; +}; + +void K_DrawCapsuleTracking(capsuletracking_t* caps) +{ + trackingResult_t result = {}; + int32_t timer = 0; + + K_ObjectTracking(&result, &caps->point, false); + + if (result.onScreen == false) + { + // Off-screen, draw alongside the borders of the screen. + // Probably the most complicated thing. + + int32_t scrVal = 240; + vector2_t screenSize = {}; + + int32_t borderSize = 7; + vector2_t borderWin = {}; + vector2_t borderDir = {}; + fixed_t borderLen = FRACUNIT; + + vector2_t arrowDir = {}; + + vector2_t arrowPos = {}; + patch_t* arrowPatch = nullptr; + int32_t arrowFlags = 0; + + vector2_t capsulePos = {}; + patch_t* capsulePatch = nullptr; + + timer = (leveltime / 3); + + screenSize.x = vid.width / vid.dupx; + screenSize.y = vid.height / vid.dupy; + + if (r_splitscreen >= 2) + { + // Half-wide screens + screenSize.x >>= 1; + borderSize >>= 1; + } + + if (r_splitscreen >= 1) + { + // Half-tall screens + screenSize.y >>= 1; + } + + scrVal = std::max(screenSize.x, screenSize.y) - 80; + + borderWin.x = screenSize.x - borderSize; + borderWin.y = screenSize.y - borderSize; + + arrowDir.x = 0; + arrowDir.y = P_MobjFlip(caps->mobj) * FRACUNIT; + + // Simply pointing towards the result doesn't work, so inaccurate hack... + borderDir.x = FixedMul( + FixedMul( + FINESINE((-result.angle >> ANGLETOFINESHIFT) & FINEMASK), + FINECOSINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK) + ), + result.fov + ); + + borderDir.y = FixedMul(FINESINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK), result.fov); + + borderLen = R_PointToDist2(0, 0, borderDir.x, borderDir.y); + + if (borderLen > 0) + { + borderDir.x = FixedDiv(borderDir.x, borderLen); + borderDir.y = FixedDiv(borderDir.y, borderLen); + } + else + { + // Eh just put it at the bottom. + borderDir.x = 0; + borderDir.y = FRACUNIT; + } + + capsulePatch = kp_capsuletarget_icon[timer & 1]; + + if (abs(borderDir.x) > abs(borderDir.y)) + { + // Horizontal arrow + arrowPatch = kp_capsuletarget_arrow[1][timer & 1]; + arrowDir.y = 0; + + if (borderDir.x < 0) + { + // LEFT + arrowDir.x = -FRACUNIT; + } + else + { + // RIGHT + arrowDir.x = FRACUNIT; + } + } + else + { + // Vertical arrow + arrowPatch = kp_capsuletarget_arrow[0][timer & 1]; + arrowDir.x = 0; + + if (borderDir.y < 0) + { + // UP + arrowDir.y = -FRACUNIT; + } + else + { + // DOWN + arrowDir.y = FRACUNIT; + } + } + + arrowPos.x = (screenSize.x >> 1) + FixedMul(scrVal, borderDir.x); + arrowPos.y = (screenSize.y >> 1) + FixedMul(scrVal, borderDir.y); + + arrowPos.x = std::clamp(arrowPos.x, borderSize, borderWin.x) * FRACUNIT; + arrowPos.y = std::clamp(arrowPos.y, borderSize, borderWin.y) * FRACUNIT; + + capsulePos.x = arrowPos.x - (arrowDir.x * 12); + capsulePos.y = arrowPos.y - (arrowDir.y * 12); + + arrowPos.x -= (arrowPatch->width << FRACBITS) >> 1; + arrowPos.y -= (arrowPatch->height << FRACBITS) >> 1; + + capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1; + capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1; + + if (arrowDir.x < 0) + { + arrowPos.x += arrowPatch->width << FRACBITS; + arrowFlags |= V_FLIP; + } + + if (arrowDir.y < 0) + { + arrowPos.y += arrowPatch->height << FRACBITS; + arrowFlags |= V_VFLIP; + } + + V_DrawFixedPatch(capsulePos.x, capsulePos.y, FRACUNIT, V_SPLITSCREEN, capsulePatch, nullptr); + + V_DrawFixedPatch(arrowPos.x, arrowPos.y, FRACUNIT, V_SPLITSCREEN | arrowFlags, arrowPatch, nullptr); + } + else + { + // Draw simple overlay. + const fixed_t farDistance = 1280 * mapobjectscale; + bool useNear = (caps->camDist < farDistance); + + patch_t* capsulePatch = nullptr; + vector2_t capsulePos = {}; + + bool visible = P_CheckSight(stplyr->mo, caps->mobj); + + if (visible == false && (leveltime & 1)) + { + // Flicker when not visible. + return; + } + + capsulePos.x = result.x; + capsulePos.y = result.y; + + if (useNear == true) + { + timer = (leveltime / 2); + capsulePatch = kp_capsuletarget_near[timer % 8]; + } + else + { + timer = (leveltime / 3); + capsulePatch = kp_capsuletarget_far[timer & 1]; + } + + capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1; + capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1; + + V_DrawFixedPatch(capsulePos.x, capsulePos.y, FRACUNIT, V_SPLITSCREEN, capsulePatch, nullptr); + } +} + +}; // namespace + +void K_drawTargetHUD(const vector3_t* origin, player_t* player) +{ + constexpr std::size_t kMaxCapsuleHUD = 32; + + std::size_t i, j; + + capsuletracking_t capsuleList[kMaxCapsuleHUD]; + std::size_t capsuleListLen = 0; + + mobj_t* mobj = nullptr; + mobj_t* next = nullptr; + + for (mobj = trackercap; mobj; mobj = next) + { + capsuletracking_t* caps = nullptr; + + next = mobj->itnext; + + if (mobj->health <= 0) + { + continue; + } + + if (mobj->type != MT_BATTLECAPSULE) + { + continue; + } + + caps = &capsuleList[capsuleListLen]; + + caps->mobj = mobj; + caps->point.x = R_InterpolateFixed(mobj->old_x, mobj->x); + caps->point.y = R_InterpolateFixed(mobj->old_y, mobj->y); + caps->point.z = R_InterpolateFixed(mobj->old_z, mobj->z); + caps->point.z += (mobj->height >> 1); + caps->camDist = R_PointToDist2(origin->x, origin->y, caps->point.x, caps->point.y); + + capsuleListLen++; + + if (capsuleListLen >= kMaxCapsuleHUD) + { + break; + } + } + + if (capsuleListLen > 0) + { + // Sort by distance from camera. + if (capsuleListLen > 1) + { + for (i = 0; i < capsuleListLen - 1; i++) + { + std::size_t swap = i; + + for (j = i + 1; j < capsuleListLen; j++) + { + capsuletracking_t* cj = &capsuleList[j]; + capsuletracking_t* cSwap = &capsuleList[swap]; + + if (cj->camDist > cSwap->camDist) + { + swap = j; + } + } + + if (swap != i) + { + capsuletracking_t temp = capsuleList[swap]; + capsuleList[swap] = capsuleList[i]; + capsuleList[i] = temp; + } + } + } + + for (i = 0; i < capsuleListLen; i++) + { + K_DrawCapsuleTracking(&capsuleList[i]); + } + } +}