Skip to content

BeatClock

namespace Griff.Scenes;
public sealed class BeatClock : Component

Keeps time with the music: counts its beats and bars as they’re heard (allowing for the sound card’s delay and the player’s own audio offset, Game.AudioOffset, which a Calibration measures), and sends BeatMessage on every beat and BarMessage on the first beat of every bar, so sound players, counters, scripts and BeatPulses can follow along, and Spawners, Shooters, Movers and Switches with Beats set step to it. It follows whatever music is playing (a BackgroundMusic’s, a room’s or a script’s) and waits while there’s none. Music made with Audio > New Music says its own tempo; for other music, set Tempo.

This is a component: its saved properties are on its component page.

public int Bar { get; }

The bar it’s on, counting from 0.

public string? BarMessage { get; set; }

Sent on the first beat of every bar, with the bar’s number (0 for the first). Empty sends nothing.

public int Beat { get; }

The beat it’s on, counting from 0; -1 before the first.

public int BeatInBar { get; }

Which beat of the bar it’s on, from 0 (the bar’s first, the downbeat) to BeatsPerBar - 1.

public string? BeatMessage { get; set; }

Sent on every beat, with the beat’s number (0 for the first) as its data. Empty sends nothing.

public float Beats { get; }

Beats heard since the first, with how far through this one: 8.5 is halfway through beat 8 (the ninth). It counts on as the music loops, and is below 0 before the first beat.

public int BeatsPerBar { get; set; }

Beats in a bar: 4 for most music, 3 for a waltz.

public float CurrentTempo { get; }

The tempo it counts at: its Tempo, or the music’s.

public bool IsPlaying { get; }

True while there’s music to keep time with.

public float Offset { get; set; }

Seconds into the music of its first beat: for music with a lead-in, or to nudge the beat later (more) or earlier (less) until it sits right. It’s the music’s, the same for everyone; how late a player’s own speakers are is their audio offset (Game.AudioOffset), which the clock allows for on top.

public float Phase { get; }

How far through the beat it is, from 0 (on it) to almost 1 (the next is due).

public float Position { get; }

Seconds into the music that have been heard (less the player’s audio offset), back to 0 each time it loops.

public float SecondsFromBeat { get; }

How far it is from the nearest beat, in seconds: negative just before it, positive just after. For timing a press to the music: if (Math.Abs(clock.SecondsFromBeat) < 0.1f) Perfect(); The player’s audio offset is allowed for, so a press on the beat as they hear it is 0.

public float SecondsPerBeat { get; }

How long a beat lasts, in seconds.

public double Shown { get; }

The beats drawn: those counted, ahead by the player’s visual offset, for what shows the beat.

public float ShownBeats { get; }

The beats to draw now: Beats ahead by the player’s visual offset (Game.VisualOffset, how late their screen shows things), so what’s drawn to the beat (a BeatPulse, notes coming down a lane) is seen just as the beat is heard. Only drawing goes by it.

public float Tempo { get; set; }

Beats a minute. 0 takes the music’s own, when it says (music made with Audio > New Music does), and otherwise counts 120.

public bool OnBeat(int every = 1, int offset = 0)

True in the frame a beat lands that’s one of every every, counting from the first, or from offset beats later: what Spawners, Shooters, Movers and Switches with Beats set step on. For a script: if (clock.OnBeat(2)) Jump();

public float SecondsFrom(double beat)

How far the music heard is past beat (counted as Beats are, so 16.5 is halfway through the seventeenth), in seconds: negative before it, positive after. The player’s audio offset is allowed for, so a press as they hear the beat reads 0: what a hit judgment compares with its windows, for a note on that beat. if (Math.Abs(clock.SecondsFrom(note)) < 0.05f) Perfect();

public event Action<int>? BarStarted

Raised on the first beat of every bar, with the bar’s number.

public event Action<int>? BeatStarted

Raised on every beat, with its number.