Skip to content

Latest commit

 

History

History
62 lines (41 loc) · 4.1 KB

DESIGN.md

File metadata and controls

62 lines (41 loc) · 4.1 KB

Technical Design

Module Responsibilities

Module Current responsibility
main.cpp Main loop, scene dispatch, log options and profiling
Game.cpp Countdown, gameplay lifecycle, spawning orchestration and song completion
Block.cpp Note generation, time-based position and automatic Miss
Input.cpp Key polling, lane matching, hit judgments and scoring
Audio.cpp Music loading, stream updates and cleanup helpers
Render.cpp Drawing, visual feedback, plus menu input and scene transitions
SongDatabase.cpp Five songs with name, BPM, file path and offset
FrameProfile.h Frame summary statistics

This is a modular starting point, not a fully separated update/render architecture. Menu drawing functions currently also modify scene state, and some resource ownership is local to rendering functions.

Rhythm and Position

Beat interval = 60 / BPM
Travel time = judge line Y / note speed
Spawn time = target time - travel time
Note Y = (current time - spawn time) * note speed

Positions are derived from elapsed time instead of accumulating per-frame displacement. Hit judgments compare timestamps independently of the rendered rectangle.

The current implementation initializes the first target from the travel time, then advances it by the beat interval and adds the song offset. Consequently, changing travel time can shift target beat alignment. This is a known limitation, not a completed synchronization solution.

Gameplay time is derived from GetTime() - musicStartTime, where the start timestamp is set when playback is requested. It is not a calibrated measurement of the audio reaching the listener. Input, note updates and rendering currently take separate time readings.

Input and Judgment

For a pressed lane, the game searches active notes in a 150 ms window and selects the nearest target time.

Event Outcome Score
Absolute timing difference <= 50 ms Perfect; consumes note +200
Difference > 50 ms and <= 100 ms Good; consumes note +100
Press outside valid hit window or without a candidate Bad; does not consume note -20
Active note passes target + 100 ms Automatic Miss -50

Miss is generated by note updates, not classified from a key press. Currently, note updates run before input handling, and an if / else if chain accepts only one lane per frame. Improving boundary handling and simultaneous inputs is planned.

Audio and Scenes

The audio device is initialized at startup. The selected music stream loads before countdown, plays after countdown, and is updated during gameplay. Completion checks use stream playback state and duration; old music is unloaded when changing songs or shutting down.

The countdown lasts four seconds: 3, 2, 1, then GO. Correcting the displayed numbers does not change music start timing.

Music validity checks exist, but loading failures, resource ownership and song-end note scheduling still need refinement. Main-menu and song-selection textures do not yet have fully centralized cleanup.

Profiling Semantics

Profiling is opt-in. A frame is selected based on the state at the beginning of the iteration: Playing, not countdown, not ending. Timing starts near the top of the loop and ends after EndDrawing(). This includes frame pacing and drawing submission, without providing a GPU completion measurement.

Samples are stored in memory and exported only on normal exit. Sorting for the summary also happens after gameplay. p95 and p99 use the nearest-rank definition; long-frame counts are strictly greater than 25 and 50 ms. Empty sessions produce zero-valued summaries and a CSV header with no samples.

Measurements across songs are combined within one process. Random lanes, manual input and background system activity limit repeatability. A controlled comparison should use the same compiled executable, terminal behavior and song, changing only verbose logging, and repeat both modes. No actual gameplay A/B result has been established yet.

See OPTIMIZATION.md for the experiment procedure and CHANGELOG.md for completed changes.