Skip to main content
The gameplay system manages the rhythm game mechanics, musical timing, scoring, and player input handling during song playback.

Core Gameplay Loop

The gameplay state (PlayState.hx) orchestrates all rhythm gaming systems:

PlayState Initialization

Key State Variables:
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, use PlayStateParams:
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

The Conductor 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)
Example (4/4 time at 120 BPM):
  • 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:
Common 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 via SongTimeChange:

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 in Scoring.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
Score Calculation:
Score Constants:
  • PBOT1_MAX_SCORE: 500 points
  • PBOT1_MIN_SCORE: 9.0 points (minimum for hit)
  • PBOT1_MISS_SCORE: -100 points
  • PBOT1_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:
  • easy
  • normal (default)
  • hard
Difficulty-specific data:

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:
  • 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 through PreciseInputManager 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)

Performance Metrics

The game tracks various tallies during gameplay:
These tallies determine the final rank and are used for leaderboards and progression tracking.