Judgment Window Lab: Timing Feel as Two Sliders
A timing lab: 20 beats, one shrinking ring, one judgment circle. Drag Perfect Window (40–150ms) and BPM (60–180) sliders to feel where timing feel comes from.
Análisis
- 20 notes per round; each hitAt lands exactly on a beat, and the ring spawns 2 beats early from the outer circle
- Click error ≤ Perfect window judges Perfect, ≤ Good window (Perfect × 2.2) judges Good, and a note left unclicked past the Good window judges Miss
- After all 20 notes resolve: Perfect + Good ≥ 60% (12 notes) clears the round
- Watch the ring shrink toward the judgment circle → click the canvas at the overlap moment → read the Perfect / Good / Miss feedback
- Perfect scores 100 + combo × 5 and extends the combo, Good scores a flat 40, Miss resets the combo to zero
- Clicks outside the Good window only flash 'Too early / late': no note is consumed and the combo survives, so experimenting costs nothing
- Judgment picks the unjudged note nearest to the click time, against game.time accumulated at a fixed 60fps step — decoupled from render frame rate
- Spawn lead time approach = 2 beats scales with BPM, so the ring's visual shrink speed is identical at any BPM; only beat spacing tightens
- Perfect window and BPM are exposed as sliders while everything else is hard-coded, keeping each experiment single-variable
Código clave
Demo
Hit Start, then click the canvas the moment the shrinking ring overlaps the judgment circle. Drag the Perfect Window and BPM sliders on the side to change judgment strictness and beat density in real time; the round settles after 20 notes.
Artículo
Judgment Window Lab: Timing Feel as Two Sliders
One-Sentence Essence
This is not a commercial game but a lab-grade minimal game instance built for the Timing archetype: 20 beats per round, one shrinking ring, one fixed judgment circle — the gameplay is compressed down to a single act, "click at the overlap moment." Its real value is turning the two knobs that define timing feel — judgment window strictness (Perfect window in ms) and beat density (BPM) — into adjustable sliders, so players and developers can drag them by hand and feel how the same primitive produces different feels under different parameters.
Behavior Loop
- A note spawns from the outer circle 2 beats early, with its hitAt landing exactly on a beat;
- The ring shrinks linearly toward the fixed judgment circle at the center, whose core dot pulses once per beat as a rhythm cue;
- The player clicks anywhere on the canvas at the moment they believe the ring overlaps the circle;
- The system picks the unjudged note nearest to the click time and compares the absolute error: within the Perfect window judges Perfect (+100 + combo × 5), within the Good window (Perfect × 2.2) judges Good (+40); beyond that it only flashes "Too early / late" and consumes no note;
- A note left unclicked past the Good window judges Miss and resets the combo to zero;
- After all 20 notes resolve, Perfect + Good ≥ 60% (12 notes) wins the round, with a one-click replay.
Gameplay Primitives
SpawnNote(hitAt)– spawn a noteapproach(2 beats) ahead of its beat, derived from BPMCompareTiming(clickTime, hitAt)– the compare primitive: absolute error as judgment inputJudgePerfect(err ≤ perfectMs)/JudgeGood(err ≤ perfectMs × 2.2)/JudgeMiss(timeout)– three-tier timing-window judgmentComboInc()/ComboReset()– combo accumulation and resetCheckPass(P + G ≥ total × 0.6)– pass-threshold comparison
Parameter Cheat Sheet
| Parameter | Meaning | Default | Adjustable Range | Unit | |-----------|---------|---------|------------------|------| | perfectMs | Perfect judgment window (±) | 80 | 40–150 (step 5) | ms | | bpm | Beat speed | 100 | 60–180 (step 5) | BPM | | total | Notes per round | 20 | fixed | notes | | approach | Spawn lead time (= seconds per beat × 2) | 2 | fixed | beats | | Good window | Multiple of the Perfect window | 2.2× | fixed | — | | Pass line | Share of Perfect + Good | 60 | fixed | % | | Perfect score | Base + combo bonus | 100 + combo × 5 | fixed | pts | | Good score | Base score | 40 | fixed | pts |
Design Trade-offs
- Only two knobs are exposed: window strictness and beat density are the entire design space of the Timing archetype — the former draws the line between "juicy feel" and "low barrier" (80ms is already casual-friendly, 40ms approaches hardcore rhythm-game territory), while the latter decides whether players play reactively (watch the ring land, then click) or rhythmically (anticipate the beat). Everything else is hard-coded so each experiment moves exactly one variable.
- No punishment for early/late clicks: a click outside the Good window only flashes "Too early / late" — no note consumed, no combo broken, zero cost to experimenting. That is a deliberate lab-instance trade-off: commercial rhythm games use ghost-tap penalties to create tension, but a lab wants players to dare to try and be able to attribute the outcome.
- Combo bonus hangs on Perfect only: Perfect scores 100 + combo × 5 while Good is a flat 40, pushing players toward chasing Perfect instead of coasting on Good — and one Miss zeroes the combo, creating a "the sharper you are, the more you earn; one slip wipes it" tension.
- A 60% pass line: missing up to 8 notes still clears the round, so beginners always finish all 20 beats and see the full settlement instead of failing out of the experiment midway.
- The invisible window is drawn on screen: a permanent "Perfect ±80ms / Good ±176ms" caption sits under the canvas — teaching transparency over immersion, which is exactly what a "lab" is for.
Implementation Notes
- Click attribution: on click, iterate all unjudged notes and judge the one whose hitAt is nearest to the current time, avoiding mis-attribution when multiple notes are on screen;
- Judgment decoupled from the time source: judgment runs against
game.time, accumulated at a fixed 60fps step — not render-frame timestamps — so frame drops never distort fairness; - Ring rendering: radius
r = R0 + (Rj − R0) × progress, linearly interpolated from remaining time over the approach window; a ring still unclicked past its hitAt turns red and keeps shrinking to a 6px floor, painting "you are late" right on its face; - BPM coupling: seconds per beat is
beat = 60 / bpmand spawn lead isapproach = beat × 2, so the ring's visual shrink speed is identical at any BPM — only beat density changes. This is the implementation key to "the BPM knob changes density, not feel"; - Miss detection lives in update: unjudged notes past the Good window judge Miss and reset the combo; the round settles the moment all 20 resolve;
- Fully static engine: the demo runs on AtomCore (hand-drawn Canvas 2D), needs no server, posts
demo:ready/demo:score/demo:completevia postMessage, acceptsdemo:restart, and iframes directly.
The way to squeeze this instance dry: play one round with the Perfect window at 150ms, then another at 40ms. The "feel collapsed / feel tightened" sensation between those two rounds is the entire design lesson of the Timing archetype.
También te puede gustar
120 seconds, 3 lives, 323 dots: eat and dodge through a block-city maze, where the 8-second power-pellet reversal is the only rhythm switch that matters.
A minimal penalty shootout: angle and power feed a probability model, every miss scores for the keeper, and a five-round sprint decides the match.

This article dissects the core mechanics of roguelike slaying games, breaking down the construction of enemy density curves to create dynamic combat pacing. It explains how director systems use calculation to control enemy distribution for screen readability, analyzes hard rules limiting special effects to ensure visual clarity, and reveals the satisfaction derived from linear enemy growth paired with exponential player damage. The guide provides actionable advice for developers to balance numerical values with player experience.