-
Notifications
You must be signed in to change notification settings - Fork 5
Gameplay Source Overview
Note
Nearly the whole page was generated with claude.ai, and hx files were used as a reference, thanks to github context integration in the site.
These files form the core gameplay systems of the engine. They handle notes, UI elements, character animations, and game state management.
Main gameplay coordinator
Central hub that manages all gameplay components and state. Implements the State interface.
-
score,misses,combo- Gameplay statistics -
health- Player health (0.0-1.0) -
accuracy- Accuracy tracker object -
songPosition- Current position in song (milliseconds) -
scrollSpeed- Note scroll speed multiplier -
downScroll- Notes scroll from top (false) or bottom (true) -
botplay- AI plays for the player -
practiceMode- Prevents death at low health -
hitbox- Timing window for hitting notes (milliseconds) -
ratingJudgementList- Rating judgement list. Refer to this to know how to deal with it when you want to make your own custom ratings :).
-
field- Character/actor management -
inputSystem- Keyboard/input handling -
noteSystem- Note spawning and rendering -
hud- UI overlay -
countdownDisp- "3, 2, 1, GO!" countdown -
pauseScreen- Pause menu
-
onStartSong- Song begins -
onStopSong- Song ends -
onDeath- Player dies -
onNoteHit- Note successfully hit -
onNoteMiss- Note missed -
onSustainComplete- Hold note completed -
onSustainRelease- Hold note released early -
onKeyPress/onKeyRelease- Key input events
-
setTime(value, playAgain)- Seek to song position (see Audio Pipeline Implementation for more about what this does) -
pause()/resume()- Pause/resume gameplay -
hitNote(note, timing, notesInOne)- Process successful note hit (can be manipulated based onnotetypeFunctionalityvalue) -
missNote(note, notesInOne)- Process missed note -
changeBpmAt(time, value, timeNum, timeDen)- Change BPM mid-song via conductor manipulation event
Character and camera management
Manages gameplay actors (player, opponent, spectator) and camera movement.
-
actors- Array of 3 actors: [spectator, opponent, player] -
spectator,opponent,player- Getters/setters for actor array indices -
targetCamera- Camera target position -
isInGameOver- Game over state active
-
beatHit(beat)- Called every musical beat -
sing(index, char, miss, shake, skipAnimation)- Trigger character singing animation -
hitNote(note, timing, notesInOne)- Update character for note hit -
missNote(note, notesInOne)- Update character for note miss -
gameOver()- Initiate game over sequence -
endGameOver(goBack)- Retry or return to menu
-
singPoses- Sing animations:["singLEFT", "singDOWN", "singUP", "singRIGHT"] -
missPoses- Miss animations:["singLEFTmiss", "singDOWNmiss", "singUPmiss", "singRIGHTmiss"]
Note spawning and rendering
Handles all note and sustain (hold note) spawning, rendering, hit detection, and input processing.
-
STRUMLINE_X_OFFSET- Horizontal offset for strumlines (50) -
STRUMLINE_Y_OFFSET- Vertical offset for upscroll (50) -
STRUMLINE_Y_OFFSET_DOWNSCROLL- Vertical offset for downscroll (150)
-
strumlines- Array of note lanes (typically 2: opponent and player) -
noteSpawner- Spawns notes based on chart data -
notePool- Reuses note objects for performance -
virtualNoteBuffer- Temporary buffer for rendered notes
-
update(pos)- Update note spawning (pos isInt64MetaNote position) -
renderNotes(pos)- Render visible notes -
drawNote(pos, note, diff, id)- Core note rendering and hit detection logic -
setScrollSpeed(value)- Change scroll speed -
resetStrumlines(resetAnims)- Reset strumline positions -
resetNotes(songPosition)- Clear and respawn notes (useful after seeking) -
onSongPositionJump(pos)- Sync bot timers after seeking/pausing
-
noteTypeFunctionalityPre- Array of callbacks for custom note types - Default behavior:
note.type % strumlines.lengthdetermines lane - Custom types route to lane 1 and trigger callback
Individual note lane
Represents one note lane (e.g., player's 4 arrows or opponent's 4 arrows).
-
x,y- Position -
scale- Receptor size -
gap- Spacing between receptors -
length- Number of receptors (mania) -
playable- Player controls this strumline (vs. bot) -
buffer- Array of receptor sprites
-
notesToHit- Notes available to hit -
notesToHit_indexes- Chart indices for notes -
sustainsToHold- Active hold notes -
sustainsToHold_duration- Duration of holds -
botTimers- Timer for bot receptor glow -
sustainsActive- Whether sustain is being held
-
press(index)- Handle key press on receptor -
release(index)- Handle key release on receptor -
confirmed(index)- Check if receptor is confirmed/hit -
draw(buf)- Add receptors to render buffer -
resetInputs()- Clear all tracked notes -
resetAnimations()- Reset receptor animations
User interface overlay
Displays score, accuracy, health bar, time bar, rating popups, and combo numbers.
-
scoreTxt- Score/misses/accuracy text -
timeBarTxt- Remaining time text -
watermarkTxt- Build watermark
-
healthBar- Health bar display -
timeBarParts- Time bar fill and background -
ratingPopup- "Sick!"/"Good!"/"Bad!"/"Shit!" popup -
comboNumbers- Combo count digits
-
render(deltaTime)- Update all HUD elements -
setHUDAlpha(alpha)- Fade in/out HUD -
respondWithRatingID(id)- Show rating popup (0=Sick, 1=Good, 2=Bad, 3=Shit) -
hideRatingPopup()- Hide rating popup -
updateScoreText(deltaTime)- Update score display -
updateTimeBarParts()- Update time bar fill -
updateBuffers()- Push changes to GPU
- 0 = Sick
- 1 = Good
- 2 = Bad
- 3 = Shit
Health bar display
Displays player/opponent health with colored bars and animated icons.
-
parts- Two health bar segments (opponent and player colors) -
bg- Background sprite -
healthIcons- Array of 2 icons (opponent, player) -
healthIconIDs- Icon frame IDs[[normal, losing], ...]
-
render(deltaTime)- Update health bar smoothly -
updateBar()- Recalculate bar segment widths -
updateHealthIcons()- Update icon positions and frames
- Opponent icon changes at >75% health
- Player icon changes at <25% health
- Icons positioned on health bar boundary
Many methods use Int64 position values (MetaNote format, AKA 50ns ticks):
- Convert from time:
MetaNote.floatToMetaNotePosition(50ns ticks) - Convert to time:
MetaNote.metaNotePositionToSongTime(position)
Many systems check parent.downScroll:
- Inverts Y positioning
- Flips scroll direction
- Adjusts strumline Y offset
-
strumline.playable- Player controls this lane - Opponent lanes typically not playable
- Botplay override: all lanes become bot-controlled
-
clear()- Remove all elements -
addElement(sprite)- Add sprite to buffer -
updateElement(sprite)- Update existing sprite -
removeElement(sprite)- Remove sprite from buffer - Call
update()to push changes to GPU
- Notes are pooled and reused (don't create new ones each frame)
- Virtual note buffer prevents duplicate rendering
- Buffers must be manually updated after changes
-
songPositionincludes latency compensation -
Main.conductor.offsetadjusts for audio/video lag - Bot timers measured in seconds, decremented each frame
-
Main.conductor.onBeatUnoffsetteddoesn't affect beat hits; crucial for countdown
- Controlled by
Field.hx - Disables input, plays death animation
- Right-click returns to menu, left-click retries
- Most events dispatch
MetaNoteobjects -
notesInOneparameter indicates stacked notes - Listen before triggering gameplay changes
But on one condition... You will most likely misuse the optimization techniques in your own game or overcomplicate them.
Please don't read this it's a joke I cocked up early in the wiki
Hello sidebar test.