group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
Game Class Reference

Top-level client game object. More...

#include <Game.hpp>

Collaboration diagram for Game:
[legend]

Classes

struct  PendingDamageNumber
struct  FrameSectionMs
 Per-frame phase-time breakdown. More...

Public Member Functions

bool init ()
 Initialise all subsystems and spawn the local player entity.
SDL_AppResult event (SDL_Event *event)
 Forward an SDL event to ImGui and handle application-level keys.
SDL_AppResult iterate ()
 Advance one frame: sample input, step physics, render.
void quit ()
 Shut down all subsystems in reverse-init order.
void refreshRemotePlayerRenderables ()
 Update Renderable components for remote players (model, scale, orientation from animation rig).
void refreshRemoteProjectileRenderables ()
 Assign Renderable components to newly spawned projectile entities.
void refreshRemoteRespawnRenderables ()
 Reset Renderable visibility for players transitioning through respawn.
void refreshDroppedWeaponRenderables ()
 Assign Renderable components to dropped-weapon entities (mirrors spawner visuals).

Private Member Functions

void applyFrameRateLimit ()
 Apply FPS-limit strategy based on limitFPSToMonitor, monitor Hz, and physics Hz.
void attachAnimatedCharacter (entt::entity e)
 Attach a fresh AnimatedCharacter component to an entity.

Private Attributes

NetworkConfig netCfg
 Runtime network config loaded from config.toml.
SDL_Window * window = nullptr
 The application window.
DebugUI debugUI
 Owns the ImGui context and SDL3 input backend.
NewRenderer renderer
 Graphics-team SDL3 GPU renderer.
Registry registry
 The shared ECS registry.
Client client
 UDP network client.
ParticleSystem particleSystem
 Client-side VFX particle system.
SfxSystem sfxSystem
 Client-side sound effects system.
Hud hud_
 In-game HUD overlay system.
entt::dispatcher dispatcher
 Event bus for weapon/impact/explosion events.
Uint64 prevTime = 0
 SDL performance counter at the last iterate() call.
float accumulator = 0.0f
 Unprocessed physics time in seconds.
int tickCount = 0
 Total physics ticks elapsed since start.
uint32_t clientPredictTick = 0
 Monotonic per-tick counter stamped onto outgoing InputSnapshots.
bool prevShootingForDebug_ = false
 PR-20: tracks last frame's input.shooting so the fire-rising-edge detector inside iterate() only captures the FIRST tick of a click (a "trigger pull"), not every tick the button is held.
InputRingBuffer inputRing_
 Phase 5b: ring buffer of recent stamped inputs for replay- based reconciliation.
bool mouseCaptured = true
 True when relative mouse mode is active.
SDL_Gamepad * activeGamepad_ = nullptr
 Currently-bound gamepad, or nullptr if none is plugged in.
SDL_JoystickID activeGamepadId_ = 0
 SDL_JoystickID of the active gamepad — needed to identify the device on SDL_EVENT_GAMEPAD_REMOVED so we don't tear down a different controller when a second one disconnects.
float gamepadLookSensitivity = 6.0f
 Right-stick look speed in radians per second at full deflection.
systems::GamepadAimAssistConfig aimAssistCfg_
 AAA-style gamepad aim assist tuning.
systems::GamepadAimAssistState aimAssistState_
 Persistent inter-frame state for aim assist (anchor on target AABB + previous-frame snapshot used to compute the angular delta from which the rotational pull is derived).
std::unique_ptr< WorkerPoolworkerPool_
 Persistent thread pool for parallel-for over per-frame loops (currently the animation update; future: parallel frustum cull, particle update, ECS transforms).
float mouseSensitivity = 0.0007f
 Radians per pixel of mouse movement.
bool renderSeparateFromPhysics = true
 Render every iterate() with interpolation (true) vs only after a physics tick (false).
bool inputSyncedWithPhysics = true
 Sample mouse once per physics tick (true) vs every iterate() call (false).
bool limitFPSToMonitor = true
 VSync on (true) / off (false).
Uint64 softLimitPeriod = 0
 Target frame period in perf-counter ticks (0 = disabled).
Uint64 softLimitNextFrame = 0
 Performance counter target for next frame deadline.
FrameRecorder recorder
 R-key toggled frame-state + screenshot recorder.
uint64_t frameCount = 0
 Monotonic render-frame counter.
glm::vec3 cachedEye_ {0.f, 100.f, 0.f}
glm::vec3 cachedCamFwd_ {0.f, 0.f, 1.f}
bool cachedGravFlipped_ {false}
 Local player gravity-flip state, updated each iterate().
float currentCameraRoll_ {0.0f}
 Smoothed camera roll angle (radians).
physics::MapCollisionData mapCollision_
AssetRegistry assets_
int wraithModelIdx = -1
int glowSphereModelIdx_ = -1
int movableSphereModelIdx_ = -1
int weaponModelIndices_ [4] = {-1, -1, -1, -1}
int weaponAssetIds_ [4] = {-1, -1, -1, -1}
int rocketProjectileModelIdx_ = -1
bool showDynLightUI_ = false
 Show the Dynamic Lighting panel.
bool showHudDebug_ = false
 Show the HUD Tweaker panel.
bool flashlightEnabled_ = false
 Point light at camera position.
float flashlightIntensity_ = 8.0f
 Flashlight brightness.
float flashlightRange_ = 800.0f
 Flashlight attenuation range.
float flashlightOffset_ = 30.0f
 Forward offset from eye.
bool movableSphereEnabled_ = false
 Glow sphere following the player.
float sphereFollowDist_ = 150.0f
 Distance ahead of player.
float sphereIntensity_ = 5.0f
 Point light intensity of movable sphere.
float sphereRange_ = 500.0f
 Point light range of movable sphere.
int glowCylinderModelIdx_ = -1
 Glow cylinder (beam) model index.
bool beamEnabled_ = false
 Show the bloom beam.
glm::vec3 beamStartOff_ {30.0f, -5.0f, 10.0f}
 Beam start offset (fwd, up, right) from eye.
glm::vec3 beamEndOff_ {200.0f, -5.0f, 10.0f}
 Beam end offset (fwd, up, right) from eye.
float beamRadius_ = 3.0f
 Beam cylinder radius.
glm::vec3 beamColor_ {0.6f, 0.1f, 1.0f}
 Beam emissive colour (purple).
float beamLightIntensity_ = 4.0f
 Point light intensity per sample.
float beamLightRange_ = 300.0f
 Point light range per sample.
float beamLightSpacing_ = 60.0f
 Distance between point lights along beam.
WeaponType currentEquippedType_ = WeaponType::Rifle
 Cached each frame.
WeaponType lastEquippedType_ = WeaponType::Rifle
 Previous frame's weapon — triggers default reload on change.
bool viewmodelDefaultsApplied_ = false
bool wasChargingRailgun_ = false
 True last frame if local player was charging RailGun.
bool wasBeamActive_ = false
 True last frame if local player's beam was active.
float hitmarkerTimer_ = 0.0f
 Remaining display time (fades out over this).
bool hitmarkerIsHeadshot_ = false
 True when the current hitmarker was a headshot.
bool hitmarkerShieldBreak_ = false
 True when the current hit depleted target armor.
std::vector< PendingDamageNumberpendingDamageNumbers_
entt::entity accumTarget_ = entt::null
 Current target being damaged.
int accumTotal_ = 0
 Running damage total.
float accumResetTimer_ = 0.f
 Timer to reset accumulator after inactivity.
uint8_t accumLastHitType_ = 0
 0=health(white), 1=shield(blue), 2=headshot(gold).
float prevHealth_ = 100.f
float prevArmor_ = 100.f
float matchElapsedSeconds_ = 0.f
 Time accumulated while the match is in PLAYING phase (s).
int prevPrimaryWeaponType_ = -1
 Last-frame snapshot of the local player's weapon-slot types (-1 = empty).
int prevSecondaryWeaponType_ = -1
int prevAmmoReserve_ = -1
 Drives "+N <weapon> AMMO" reserve-grow notifications.
std::vector< HudPickupNotificationpendingPickupNotifications_
 Pickup notifications queued for the next HUD frame.
float vmScale = 1.0f
 Weapon model scale (model is in mm).
float vmForward = 0.0f
 Forward offset from eye (Quake units).
float vmRight = 0.0f
 Right offset from eye.
float vmDown = 0.0f
 Downward offset from eye.
float vmYawOffset = 0.0f
 Extra yaw (degrees) applied to the model before camera orient.
float vmPitchOffset = 0.0f
 Extra pitch (degrees).
float vmRollOffset = 0.0f
 Extra roll (degrees).
bool showViewmodelUI = false
 Show the Viewmodel Tweaker window.
float prevSwayYaw_ = 0.0f
float prevSwayPitch_ = 0.0f
float swayOffsetX_ = 0.0f
 Current horizontal sway (right axis, Quake units).
float swayOffsetY_ = 0.0f
 Current vertical sway (up axis).
bool swayInitialized_ = false
 Guard against initial delta spike.
float swayAmplitudeYaw_ = 3.0f
float swayAmplitudePitch_ = 2.0f
float swayDecayRate_ = 8.0f
 Exponential decay speed.
float swaySmoothing_ = 0.15f
 Input smoothing (0..1, lower = smoother).
float recoilPitch_ = 0.0f
 Current recoil pitch offset (degrees).
float recoilPushBack_ = 0.0f
 Current recoil backward offset (Quake units).
float recoilRoll_ = 0.0f
 Current recoil roll offset (degrees).
float localFireCooldown_ = 0.0f
 Countdown timer; fire VFX only when <= 0.
int pendingScrollSwitch_ = 0
 +1 = next slot, -1 = previous slot, consumed each frame.
ThirdPersonWeaponParams tpWeaponParams_ [4]
 Runtime-tunable copy; initialised from defaults.
int tpTuneWeaponIdx_ = 0
 Which weapon type is being tuned.
bool showTPWeaponUI_ = false
 Show the 3P Weapon Tweaker window.
CharacterRig charRig_
 Shared skinned rig (skeleton + bind pose + weights).
AnimationLibrary animLibrary_
 Collection of ozz clips on the shared rig.
CpuLbsSkinningBackend skinBackend_
 Phase-1 CPU linear-blend-skinning backend.
AnimationTesterState animUI_
 Persistent state for the Animation Tester panel.
HitboxRig clientHitboxRig_
 Hitbox definitions for client-side debug visualization.
float kRigScale_ = 1.0f
 Per-renderable scale for animated characters (auto-calculated, tunable).
float kRigVerticalOffset_
 Per-renderable Y translation for animated characters (auto-calculated, tunable).
float rigMeshMinY_ = 0.0f
 Minimum Y of the bind-pose mesh vertices (model space).
float fpsHistory [k_fpsHistorySize] = {}
 Circular buffer of per-frame FPS samples.
int fpsHistoryHead = 0
 Next write index.
int fpsHistoryCount = 0
 Valid sample count (saturates at k_fpsHistorySize).
Uint64 prevRenderTime = 0
 Perf counter at the last render call.
float pingTimer = 0.0f
 Accumulator for periodic PING sends.
Uint64 statsPrevTime = 0
 Perf counter at the last stats snapshot.
int statsPhysTicks = 0
 Physics ticks accumulated since last snapshot.
float measuredPhysicsHz = 0.0f
 Computed physics rate (Hz).
float statsFPSCurrent = 0.0f
 Most-recent render FPS sample.
float statsFPSMin = 0.0f
 Minimum FPS in the ring buffer.
float statsFPSMax = 0.0f
 Maximum FPS in the ring buffer.
float statsFPS1pLow = 0.0f
 1st-percentile FPS (1 % low).
float statsFPS5pLow = 0.0f
 5th-percentile FPS (5 % low).
float benchSeconds_ = 0.0f
 Bench duration in seconds (0 = disabled).
Uint64 benchStartTime_ = 0
 Perf counter at first iterate() in bench mode.
bool benchActive_ = false
 True after BENCH_SECONDS read at init.
std::vector< float > benchFrameTimesMs_
 Per-frame ms after warmup; reservation in init().
std::vector< FrameSectionMsbenchFrameStats_
MatchPhase currentMatchPhase = MatchPhase::WARMUP
 Latest match phase update from the server.
float countdownTimer = 0.0f
 Countdown timer for transitions between match phases (e.g. warmup to in-progress).
std::vector< KillFeedEventkillFeed
 Recent kill events for on-screen kill feed (newest first).

Static Private Attributes

static constexpr int k_physicsHz = 128
 Target physics tick rate.
static constexpr float k_physicsDt = 1.0f / static_cast<float>(k_physicsHz)
 Seconds per tick.
static constexpr int k_maxTicksPerFrame = 2
 Spiral-of-death guard: max physics ticks per iterate().
static constexpr int k_fpsHistorySize = 512
 Samples in the rolling FPS ring buffer.
static constexpr float k_benchWarmupSeconds = 2.0f
 Skip the first N seconds (pipeline warmup).

Detailed Description

Top-level client game object.

Owns all subsystems: window, ECS registry, renderer, debug UI, and network client. Wired into SDL's application-callback API (SDL_AppInit / SDL_AppEvent / SDL_AppIterate / SDL_AppQuit).

Member Function Documentation

◆ applyFrameRateLimit()

void Game::applyFrameRateLimit ( )
private

Apply FPS-limit strategy based on limitFPSToMonitor, monitor Hz, and physics Hz.

Advance one frame: decoupled physics / render loop.

When monitor refresh >= physics Hz, uses VSync. Otherwise falls back to a software frame limiter at physics Hz with mailbox/immediate presentation.

Physics ALWAYS runs at exactly 128 Hz (k_physicsHz) using an accumulator with a multi-tick catch-up loop (up to k_maxTicksPerFrame per call). This is non-negotiable: it must match the server tick rate.

Input is split into two independent streams:

Mouse look (yaw / pitch) – sampled EVERY iterate() call so camera rotation is perfectly smooth at whatever frame rate the renderer produces. The camera always uses the latest yaw directly (never interpolated). Interpolating yaw with the physics alpha creates a timebase mismatch on multi-tick or zero-tick frames, producing visible jitter.

Movement keys (WASD / jump / crouch) – sampled once per physics tick group when inputSyncedWithPhysics is true (the default) so movement calculations match the server. When the toggle is off, keys are also sampled every iterate() call.

Position interpolation uses alpha = accumulator / k_physicsDt across the LAST physics tick (PreviousPosition is saved inside the while loop before each tick).

Three ImGui-tunable flags:

renderSeparateFromPhysics – render every iterate() call with position interpolated between the last two physics ticks (true, default) vs. render only after a physics tick (false, caps render fps at 128 Hz).

inputSyncedWithPhysics – sample movement keys once per tick group (true, default, server-consistent) vs. every iterate() call (false). Mouse look is always per-frame regardless of this toggle.

limitFPSToMonitor – when ON and monitor >= physicsHz, uses VSync. When monitor < physicsHz (regardless of this toggle), a software frame limiter at physicsHz is always active to ensure rock-steady frame pacing — the monitor can't display above its refresh rate anyway, and uncapped rendering creates beat-frequency jitter.

Here is the caller graph for this function:

◆ attachAnimatedCharacter()

void Game::attachAnimatedCharacter ( entt::entity e)
private

Attach a fresh AnimatedCharacter component to an entity.

Creates a new CharacterAnimator wired to the shared rig + clip library + skinning backend, uploads a per-entity clone of the rig's template model, and emplaces the component. Safe to call even if the rig failed to load (logs a warning and leaves the entity un-animated).

Here is the caller graph for this function:

◆ event()

SDL_AppResult Game::event ( SDL_Event * event)

Forward an SDL event to ImGui and handle application-level keys.

Parameters
eventThe SDL event to process.
Returns
SDL_APP_SUCCESS to quit, SDL_APP_CONTINUE to keep running.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init()

bool Game::init ( )

Initialise all subsystems and spawn the local player entity.

Returns
False on any fatal initialisation error.
Here is the call graph for this function:

◆ iterate()

SDL_AppResult Game::iterate ( )

Advance one frame: sample input, step physics, render.

Execution flow each frame:

  1. Time accumulation — compute frame delta, detect suspend/background gaps, clamp to avoid spiral-of-death.
  2. Performance stats — refresh FPS percentiles and physics Hz every 0.5 s.
  3. Input sampling — mouse look runs every frame for smooth camera; movement keys run once per physics tick group when inputSyncedWithPhysics is true; weapon keys sampled every frame.
  4. Network — send input to server, send periodic pings, poll bandwidth.
  5. Physics — drain accumulator at 128 Hz (up to k_maxTicksPerFrame), snapshot PreviousPosition, poll network for state updates, refresh remote renderables.
  6. Camera resolve — interpolate local player position between ticks (or use post-tick position in sequential mode).
  7. Local weapon VFX — fire cooldown, spawn tracers/impacts, visual recoil kick (viewmodel-only, does not affect aim).
  8. Subsystem updates — flush dispatcher events, update particles, SFX, skeletal animation (CPU skinning + hitbox capsules).
  9. Entity render list — build world-space transforms for entities, third-person weapons, glow spheres, beam visuals, point lights.

Viewmodel — weapon sway, bob, recoil decay, camera-space transform.

  1. Frame recording — if R-key recording is active, capture frame state.
  2. FPS ring buffer — record inter-render delta for stats.
  3. Debug UI — ImGui panels (debug menu, network, particles, hitbox, lighting, viewmodel tweaker, 3P weapon tweaker, scoreboard).
  4. HUD — gather game state, update and render the HUD overlay.
  5. Render — drawFrame with interpolated camera, apply VSync changes.
  6. Software frame limiter — sleep + spin-wait if targeting above monitor refresh rate.
Returns
SDL_APP_CONTINUE normally; SDL_APP_SUCCESS on quit request.
See also
ServerGame::tick for the authoritative server-side equivalent.

< rgb=color, a=blend factor (0=no tint).

< call animator->update()

< write to instance/palette slots

< index into skinnedInstances + base into bonePalette

Here is the call graph for this function:

◆ quit()

void Game::quit ( )

Shut down all subsystems in reverse-init order.

Here is the caller graph for this function:

◆ refreshDroppedWeaponRenderables()

void Game::refreshDroppedWeaponRenderables ( )

Assign Renderable components to dropped-weapon entities (mirrors spawner visuals).

Here is the caller graph for this function:

◆ refreshRemotePlayerRenderables()

void Game::refreshRemotePlayerRenderables ( )

Update Renderable components for remote players (model, scale, orientation from animation rig).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ refreshRemoteProjectileRenderables()

void Game::refreshRemoteProjectileRenderables ( )

Assign Renderable components to newly spawned projectile entities.

Here is the caller graph for this function:

◆ refreshRemoteRespawnRenderables()

void Game::refreshRemoteRespawnRenderables ( )

Reset Renderable visibility for players transitioning through respawn.

Here is the caller graph for this function:

Member Data Documentation

◆ accumLastHitType_

uint8_t Game::accumLastHitType_ = 0
private

0=health(white), 1=shield(blue), 2=headshot(gold).

◆ accumResetTimer_

float Game::accumResetTimer_ = 0.f
private

Timer to reset accumulator after inactivity.

◆ accumTarget_

entt::entity Game::accumTarget_ = entt::null
private

Current target being damaged.

◆ accumTotal_

int Game::accumTotal_ = 0
private

Running damage total.

◆ accumulator

float Game::accumulator = 0.0f
private

Unprocessed physics time in seconds.

◆ activeGamepad_

SDL_Gamepad* Game::activeGamepad_ = nullptr
private

Currently-bound gamepad, or nullptr if none is plugged in.

Opened on SDL_EVENT_GAMEPAD_ADDED (first device wins — extra controllers are ignored until the active one disconnects), closed on SDL_EVENT_GAMEPAD_REMOVED. SDL3's gamepad mapping database normalises every supported controller (Xbox 360 / One, DualShock, Switch Pro, ...) onto the same logical buttons + axes, so the input mapping in InputSampleSystem.hpp works uniformly across devices.

◆ activeGamepadId_

SDL_JoystickID Game::activeGamepadId_ = 0
private

SDL_JoystickID of the active gamepad — needed to identify the device on SDL_EVENT_GAMEPAD_REMOVED so we don't tear down a different controller when a second one disconnects.

◆ aimAssistCfg_

systems::GamepadAimAssistConfig Game::aimAssistCfg_
private

AAA-style gamepad aim assist tuning.

Active only when a gamepad is connected (mouse input is unaffected). Defaults are tuned for assist not auto-aim: a stationary enemy gets zero rotational pull, a moving enemy gets partial tracking help. Live-tunable from the ECS inspector.

◆ aimAssistState_

systems::GamepadAimAssistState Game::aimAssistState_
private

Persistent inter-frame state for aim assist (anchor on target AABB + previous-frame snapshot used to compute the angular delta from which the rotational pull is derived).

Reset implicitly when the target is lost or aim assist is disabled.

◆ animLibrary_

AnimationLibrary Game::animLibrary_
private

Collection of ozz clips on the shared rig.

◆ animUI_

AnimationTesterState Game::animUI_
private

Persistent state for the Animation Tester panel.

◆ assets_

AssetRegistry Game::assets_
private

◆ beamColor_

glm::vec3 Game::beamColor_ {0.6f, 0.1f, 1.0f}
private

Beam emissive colour (purple).

◆ beamEnabled_

bool Game::beamEnabled_ = false
private

Show the bloom beam.

◆ beamEndOff_

glm::vec3 Game::beamEndOff_ {200.0f, -5.0f, 10.0f}
private

Beam end offset (fwd, up, right) from eye.

◆ beamLightIntensity_

float Game::beamLightIntensity_ = 4.0f
private

Point light intensity per sample.

◆ beamLightRange_

float Game::beamLightRange_ = 300.0f
private

Point light range per sample.

◆ beamLightSpacing_

float Game::beamLightSpacing_ = 60.0f
private

Distance between point lights along beam.

◆ beamRadius_

float Game::beamRadius_ = 3.0f
private

Beam cylinder radius.

◆ beamStartOff_

glm::vec3 Game::beamStartOff_ {30.0f, -5.0f, 10.0f}
private

Beam start offset (fwd, up, right) from eye.

◆ benchActive_

bool Game::benchActive_ = false
private

True after BENCH_SECONDS read at init.

◆ benchFrameStats_

std::vector<FrameSectionMs> Game::benchFrameStats_
private

◆ benchFrameTimesMs_

std::vector<float> Game::benchFrameTimesMs_
private

Per-frame ms after warmup; reservation in init().

◆ benchSeconds_

float Game::benchSeconds_ = 0.0f
private

Bench duration in seconds (0 = disabled).

◆ benchStartTime_

Uint64 Game::benchStartTime_ = 0
private

Perf counter at first iterate() in bench mode.

◆ cachedCamFwd_

glm::vec3 Game::cachedCamFwd_ {0.f, 0.f, 1.f}
private

◆ cachedEye_

glm::vec3 Game::cachedEye_ {0.f, 100.f, 0.f}
private

◆ cachedGravFlipped_

bool Game::cachedGravFlipped_ {false}
private

Local player gravity-flip state, updated each iterate().

◆ charRig_

CharacterRig Game::charRig_
private

Shared skinned rig (skeleton + bind pose + weights).

◆ client

Client Game::client
private

UDP network client.

◆ clientHitboxRig_

HitboxRig Game::clientHitboxRig_
private

Hitbox definitions for client-side debug visualization.

◆ clientPredictTick

uint32_t Game::clientPredictTick = 0
private

Monotonic per-tick counter stamped onto outgoing InputSnapshots.

Bumped once per physics tick group inside iterate() and copied into the local player's InputSnapshot.tick before each send. The server uses this to dedup re-sent inputs (multi-input redundancy) and apply only inputs newer than its lastAppliedInputTick. Phase-5 prediction also keys the input ring buffer by it.

◆ countdownTimer

float Game::countdownTimer = 0.0f
private

Countdown timer for transitions between match phases (e.g. warmup to in-progress).

◆ currentCameraRoll_

float Game::currentCameraRoll_ {0.0f}
private

Smoothed camera roll angle (radians).

◆ currentEquippedType_

WeaponType Game::currentEquippedType_ = WeaponType::Rifle
private

Cached each frame.

◆ currentMatchPhase

MatchPhase Game::currentMatchPhase = MatchPhase::WARMUP
private

Latest match phase update from the server.

◆ debugUI

DebugUI Game::debugUI
private

Owns the ImGui context and SDL3 input backend.

◆ dispatcher

entt::dispatcher Game::dispatcher
private

Event bus for weapon/impact/explosion events.

◆ flashlightEnabled_

bool Game::flashlightEnabled_ = false
private

Point light at camera position.

◆ flashlightIntensity_

float Game::flashlightIntensity_ = 8.0f
private

Flashlight brightness.

◆ flashlightOffset_

float Game::flashlightOffset_ = 30.0f
private

Forward offset from eye.

◆ flashlightRange_

float Game::flashlightRange_ = 800.0f
private

Flashlight attenuation range.

◆ fpsHistory

float Game::fpsHistory[k_fpsHistorySize] = {}
private

Circular buffer of per-frame FPS samples.

◆ fpsHistoryCount

int Game::fpsHistoryCount = 0
private

Valid sample count (saturates at k_fpsHistorySize).

◆ fpsHistoryHead

int Game::fpsHistoryHead = 0
private

Next write index.

◆ frameCount

uint64_t Game::frameCount = 0
private

Monotonic render-frame counter.

◆ gamepadLookSensitivity

float Game::gamepadLookSensitivity = 6.0f
private

Right-stick look speed in radians per second at full deflection.

6.0 rad/s ≈ 343°/s — most testers found 3.0 too sluggish for tracking players during firefights; this is in line with mainstream console FPS defaults. Tunable from the ECS inspector.

◆ glowCylinderModelIdx_

int Game::glowCylinderModelIdx_ = -1
private

Glow cylinder (beam) model index.

◆ glowSphereModelIdx_

int Game::glowSphereModelIdx_ = -1
private

◆ hitmarkerIsHeadshot_

bool Game::hitmarkerIsHeadshot_ = false
private

True when the current hitmarker was a headshot.

◆ hitmarkerShieldBreak_

bool Game::hitmarkerShieldBreak_ = false
private

True when the current hit depleted target armor.

◆ hitmarkerTimer_

float Game::hitmarkerTimer_ = 0.0f
private

Remaining display time (fades out over this).

◆ hud_

Hud Game::hud_
private

In-game HUD overlay system.

◆ inputRing_

InputRingBuffer Game::inputRing_
private

Phase 5b: ring buffer of recent stamped inputs for replay- based reconciliation.

Each entry is keyed by clientPredictTick so runReconciliation can look up the input that was sent for any recent tick and feed it back into runMovement during replay.

◆ inputSyncedWithPhysics

bool Game::inputSyncedWithPhysics = true
private

Sample mouse once per physics tick (true) vs every iterate() call (false).

◆ k_benchWarmupSeconds

float Game::k_benchWarmupSeconds = 2.0f
staticconstexprprivate

Skip the first N seconds (pipeline warmup).

◆ k_fpsHistorySize

int Game::k_fpsHistorySize = 512
staticconstexprprivate

Samples in the rolling FPS ring buffer.

◆ k_maxTicksPerFrame

int Game::k_maxTicksPerFrame = 2
staticconstexprprivate

Spiral-of-death guard: max physics ticks per iterate().

Dropped from 8 to 2 in Phase 3g — the bench profiler showed the slowest frames are dominated by catch-up bursts (e.g. 8 ticks × ~2 ms = 16 ms in one frame, dragging p1/p5). Capping at 2 spreads the catch-up across more render frames so any individual frame's worst case is ~4 ms instead of ~16 ms. Visual consequence on a stall: physics simulation briefly runs 0.5× wall speed until the accumulator drains naturally; human-imperceptible at 1000+ render Hz.

◆ k_physicsDt

float Game::k_physicsDt = 1.0f / static_cast<float>(k_physicsHz)
staticconstexprprivate

Seconds per tick.

◆ k_physicsHz

int Game::k_physicsHz = 128
staticconstexprprivate

Target physics tick rate.

◆ killFeed

std::vector<KillFeedEvent> Game::killFeed
private

Recent kill events for on-screen kill feed (newest first).

◆ kRigScale_

float Game::kRigScale_ = 1.0f
private

Per-renderable scale for animated characters (auto-calculated, tunable).

◆ kRigVerticalOffset_

float Game::kRigVerticalOffset_
private
Initial value:
=
-90.0f

Per-renderable Y translation for animated characters (auto-calculated, tunable).

◆ lastEquippedType_

WeaponType Game::lastEquippedType_ = WeaponType::Rifle
private

Previous frame's weapon — triggers default reload on change.

◆ limitFPSToMonitor

bool Game::limitFPSToMonitor = true
private

VSync on (true) / off (false).

◆ localFireCooldown_

float Game::localFireCooldown_ = 0.0f
private

Countdown timer; fire VFX only when <= 0.

◆ mapCollision_

physics::MapCollisionData Game::mapCollision_
private

◆ matchElapsedSeconds_

float Game::matchElapsedSeconds_ = 0.f
private

Time accumulated while the match is in PLAYING phase (s).

Drives the top-center match-header readout. Reset on phase changes other than PLAYING so a fresh match starts at 0:00.

◆ measuredPhysicsHz

float Game::measuredPhysicsHz = 0.0f
private

Computed physics rate (Hz).

◆ mouseCaptured

bool Game::mouseCaptured = true
private

True when relative mouse mode is active.

◆ mouseSensitivity

float Game::mouseSensitivity = 0.0007f
private

Radians per pixel of mouse movement.

◆ movableSphereEnabled_

bool Game::movableSphereEnabled_ = false
private

Glow sphere following the player.

◆ movableSphereModelIdx_

int Game::movableSphereModelIdx_ = -1
private

◆ netCfg

NetworkConfig Game::netCfg
private

Runtime network config loaded from config.toml.

◆ particleSystem

ParticleSystem Game::particleSystem
private

Client-side VFX particle system.

◆ pendingDamageNumbers_

std::vector<PendingDamageNumber> Game::pendingDamageNumbers_
private

◆ pendingPickupNotifications_

std::vector<HudPickupNotification> Game::pendingPickupNotifications_
private

Pickup notifications queued for the next HUD frame.

Emitted when the local player's WeaponState gains a new weapon type or their reserve ammo grows beyond the previous frame's reading.

◆ pendingScrollSwitch_

int Game::pendingScrollSwitch_ = 0
private

+1 = next slot, -1 = previous slot, consumed each frame.

◆ pingTimer

float Game::pingTimer = 0.0f
private

Accumulator for periodic PING sends.

◆ prevAmmoReserve_

int Game::prevAmmoReserve_ = -1
private

Drives "+N <weapon> AMMO" reserve-grow notifications.

◆ prevArmor_

float Game::prevArmor_ = 100.f
private

◆ prevHealth_

float Game::prevHealth_ = 100.f
private

◆ prevPrimaryWeaponType_

int Game::prevPrimaryWeaponType_ = -1
private

Last-frame snapshot of the local player's weapon-slot types (-1 = empty).

Used to detect new weapons appearing → emit a pickup notification ("+1 RIFLE") so the side feed reflects what just changed.

◆ prevRenderTime

Uint64 Game::prevRenderTime = 0
private

Perf counter at the last render call.

◆ prevSecondaryWeaponType_

int Game::prevSecondaryWeaponType_ = -1
private

◆ prevShootingForDebug_

bool Game::prevShootingForDebug_ = false
private

PR-20: tracks last frame's input.shooting so the fire-rising-edge detector inside iterate() only captures the FIRST tick of a click (a "trigger pull"), not every tick the button is held.

Survives across frames as a member; is naturally reset when the local player respawns because the View<LocalPlayer> branch returns early during the dead-window (no InputSnapshot present). Implementation detail of the shot-debug visualizer.

◆ prevSwayPitch_

float Game::prevSwayPitch_ = 0.0f
private

◆ prevSwayYaw_

float Game::prevSwayYaw_ = 0.0f
private

◆ prevTime

Uint64 Game::prevTime = 0
private

SDL performance counter at the last iterate() call.

◆ recoilPitch_

float Game::recoilPitch_ = 0.0f
private

Current recoil pitch offset (degrees).

◆ recoilPushBack_

float Game::recoilPushBack_ = 0.0f
private

Current recoil backward offset (Quake units).

◆ recoilRoll_

float Game::recoilRoll_ = 0.0f
private

Current recoil roll offset (degrees).

◆ recorder

FrameRecorder Game::recorder
private

R-key toggled frame-state + screenshot recorder.

◆ registry

Registry Game::registry
private

The shared ECS registry.

◆ renderer

NewRenderer Game::renderer
private

Graphics-team SDL3 GPU renderer.

◆ renderSeparateFromPhysics

bool Game::renderSeparateFromPhysics = true
private

Render every iterate() with interpolation (true) vs only after a physics tick (false).

◆ rigMeshMinY_

float Game::rigMeshMinY_ = 0.0f
private

Minimum Y of the bind-pose mesh vertices (model space).

◆ rocketProjectileModelIdx_

int Game::rocketProjectileModelIdx_ = -1
private

◆ sfxSystem

SfxSystem Game::sfxSystem
private

Client-side sound effects system.

◆ showDynLightUI_

bool Game::showDynLightUI_ = false
private

Show the Dynamic Lighting panel.

◆ showHudDebug_

bool Game::showHudDebug_ = false
private

Show the HUD Tweaker panel.

◆ showTPWeaponUI_

bool Game::showTPWeaponUI_ = false
private

Show the 3P Weapon Tweaker window.

◆ showViewmodelUI

bool Game::showViewmodelUI = false
private

Show the Viewmodel Tweaker window.

◆ skinBackend_

CpuLbsSkinningBackend Game::skinBackend_
private

Phase-1 CPU linear-blend-skinning backend.

◆ softLimitNextFrame

Uint64 Game::softLimitNextFrame = 0
private

Performance counter target for next frame deadline.

◆ softLimitPeriod

Uint64 Game::softLimitPeriod = 0
private

Target frame period in perf-counter ticks (0 = disabled).

◆ sphereFollowDist_

float Game::sphereFollowDist_ = 150.0f
private

Distance ahead of player.

◆ sphereIntensity_

float Game::sphereIntensity_ = 5.0f
private

Point light intensity of movable sphere.

◆ sphereRange_

float Game::sphereRange_ = 500.0f
private

Point light range of movable sphere.

◆ statsFPS1pLow

float Game::statsFPS1pLow = 0.0f
private

1st-percentile FPS (1 % low).

◆ statsFPS5pLow

float Game::statsFPS5pLow = 0.0f
private

5th-percentile FPS (5 % low).

◆ statsFPSCurrent

float Game::statsFPSCurrent = 0.0f
private

Most-recent render FPS sample.

◆ statsFPSMax

float Game::statsFPSMax = 0.0f
private

Maximum FPS in the ring buffer.

◆ statsFPSMin

float Game::statsFPSMin = 0.0f
private

Minimum FPS in the ring buffer.

◆ statsPhysTicks

int Game::statsPhysTicks = 0
private

Physics ticks accumulated since last snapshot.

◆ statsPrevTime

Uint64 Game::statsPrevTime = 0
private

Perf counter at the last stats snapshot.

◆ swayAmplitudePitch_

float Game::swayAmplitudePitch_ = 2.0f
private

◆ swayAmplitudeYaw_

float Game::swayAmplitudeYaw_ = 3.0f
private

◆ swayDecayRate_

float Game::swayDecayRate_ = 8.0f
private

Exponential decay speed.

◆ swayInitialized_

bool Game::swayInitialized_ = false
private

Guard against initial delta spike.

◆ swayOffsetX_

float Game::swayOffsetX_ = 0.0f
private

Current horizontal sway (right axis, Quake units).

◆ swayOffsetY_

float Game::swayOffsetY_ = 0.0f
private

Current vertical sway (up axis).

◆ swaySmoothing_

float Game::swaySmoothing_ = 0.15f
private

Input smoothing (0..1, lower = smoother).

◆ tickCount

int Game::tickCount = 0
private

Total physics ticks elapsed since start.

◆ tpTuneWeaponIdx_

int Game::tpTuneWeaponIdx_ = 0
private

Which weapon type is being tuned.

◆ tpWeaponParams_

ThirdPersonWeaponParams Game::tpWeaponParams_[4]
private

Runtime-tunable copy; initialised from defaults.

◆ viewmodelDefaultsApplied_

bool Game::viewmodelDefaultsApplied_ = false
private

◆ vmDown

float Game::vmDown = 0.0f
private

Downward offset from eye.

◆ vmForward

float Game::vmForward = 0.0f
private

Forward offset from eye (Quake units).

◆ vmPitchOffset

float Game::vmPitchOffset = 0.0f
private

Extra pitch (degrees).

◆ vmRight

float Game::vmRight = 0.0f
private

Right offset from eye.

◆ vmRollOffset

float Game::vmRollOffset = 0.0f
private

Extra roll (degrees).

◆ vmScale

float Game::vmScale = 1.0f
private

Weapon model scale (model is in mm).

◆ vmYawOffset

float Game::vmYawOffset = 0.0f
private

Extra yaw (degrees) applied to the model before camera orient.

◆ wasBeamActive_

bool Game::wasBeamActive_ = false
private

True last frame if local player's beam was active.

◆ wasChargingRailgun_

bool Game::wasChargingRailgun_ = false
private

True last frame if local player was charging RailGun.

◆ weaponAssetIds_

int Game::weaponAssetIds_[4] = {-1, -1, -1, -1}
private

◆ weaponModelIndices_

int Game::weaponModelIndices_[4] = {-1, -1, -1, -1}
private

◆ window

SDL_Window* Game::window = nullptr
private

The application window.

◆ workerPool_

std::unique_ptr<WorkerPool> Game::workerPool_
private

Persistent thread pool for parallel-for over per-frame loops (currently the animation update; future: parallel frustum cull, particle update, ECS transforms).

Initialised in Game::init with a worker count derived from std::thread::hardware_concurrency() / 2 (or GROUP2_WORKERS if set), so we leave half the cores for the rest of the system. Gated behind a unique_ptr so it constructs AFTER init() reads the env override.

◆ wraithModelIdx

int Game::wraithModelIdx = -1
private

The documentation for this class was generated from the following files: