Core Gameplay Loop
The gameplay state (PlayState.hx) orchestrates all rhythm gaming systems:
PlayState Initialization
Song
The currently playing song instance with metadata and chart data
Float
Player’s current health value (starts at
Constants.HEALTH_STARTING)Int
Player’s accumulated score for the current song
Float
default:"1.0"
Song playback speed multiplier (1.0 = normal speed)
PlayState Parameters
When creating a PlayState instance, usePlayStateParams:
Song
required
The song to play
String
default:"Constants.DEFAULT_DIFFICULTY"
The difficulty to play the song on
Bool
default:"false"
Whether the song should start in Practice Mode
Bool
default:"false"
Whether the song should start in Bot Play Mode
Float
default:"0.0"
If specified, the game will jump to this timestamp (in ms) after countdown
Conductor & Timing System
TheConductor class handles musical timing throughout the game:
Musical Time Units
Understanding the timing hierarchy:- Step: Quarter of a beat (4/4 time = 16 steps per measure)
- Beat: Quarter note in 4/4 time (determined by time signature denominator)
- Measure: Complete bar of music (determined by time signature numerator)
- 120 BPM = 2 beats per second
- 1 beat = 4 steps
- 1 measure = 4 beats = 16 steps
- 120 BPM = 8 steps per second
Time Signatures
The Conductor supports variable time signatures:- 4/4: 4 beats per measure, quarter note gets the beat
- 3/4: 3 beats per measure, quarter note gets the beat
- 7/8: 7 beats per measure, eighth note gets the beat
- 6/8: 6 beats per measure, eighth note gets the beat
BPM and Time Changes
Songs can have multiple BPM changes defined viaSongTimeChange:
Timing Signals
The Conductor dispatches signals for game events:Offsets
Multiple offset types compensate for timing discrepancies:Float
Offset tied to the chart to compensate for instrumental delay
Float
Offset tied to the audio file format
Int
User-configured offset to compensate for input lag (from save file)
Int
User-configured offset to compensate for audio/visual lag (from save file)
Scoring System
FNF supports multiple scoring systems defined inScoring.hx:
Scoring Systems
PBOT1 Scoring (Default)
PBOT1 uses a sigmoid curve for scoring based on timing accuracy: Judgement Thresholds:Float
default:"45.0"
Notes hit within 45ms are judged as “Sick”
Float
default:"90.0"
Notes hit within 90ms are judged as “Good”
Float
default:"135.0"
Notes hit within 135ms are judged as “Bad”
Float
default:"160.0"
Notes hit within 160ms are judged as “Shit”
Float
default:"160.0"
Notes beyond 160ms are missed
PBOT1_MAX_SCORE: 500 pointsPBOT1_MIN_SCORE: 9.0 points (minimum for hit)PBOT1_MISS_SCORE: -100 pointsPBOT1_PERFECT_THRESHOLD: 5ms (always max score)
Legacy Scoring
Step-function based scoring from older versions:Ranking System
Players receive ranks based on completion percentage:Difficulty System
Difficulty Levels
Songs support multiple difficulty levels, each with separate chart data: Default difficulties:easynormal(default)hard
Scroll Speed
Controls how fast notes approach the strumline:Health System
Player health affects gameplay outcome: Health changes:- Hitting notes increases health
- Missing notes decreases health
- Health reaches 0 = Game Over
- Health > max = clamped to maximum
Constants.HEALTH_STARTING: Initial health value- Health range: typically 0.0 to 2.0
Practice & Bot Modes
Practice Mode
Allows practicing without affecting scores:- No score saving
- Can restart freely
- Debug information available
Bot Play Mode
Automatic perfect gameplay:- All notes hit automatically
- Used for testing/demonstration
- No score saving
Input Handling
Player input is processed throughPreciseInputManager for accurate timing:
- Timestamps are captured at frame-level precision
- Input is compared against Conductor timing
- Supports multiple input methods (keyboard, controller, touch on mobile)
