About this aim trainer

A small, fast, dependency-free target-clicking drill for practicing flick aim in a browser tab. No account, no upload, and nothing you click is ever recorded anywhere but your own browser's local storage.

How a round works

Starting a round spawns one target in Flick mode, or three in Grid mode, at a random position inside the play area — constrained so the whole circular target stays fully inside the box, never spawning with an edge clipped off-screen. Clicking a target counts a hit and immediately spawns its replacement somewhere new; clicking anywhere else inside the play area while the round is running counts a miss. The round ends automatically once the chosen duration has elapsed, and any targets still on screen at that instant are cleared without penalty.

How the numbers are calculated

  • Accuracy is hits / (hits + misses) × 100, shown to one decimal place. A round with zero clicks of any kind reports 0%, not an undefined value.
  • Targets per second is hits / duration, where duration is the fixed length you chose (15, 30 or 60 seconds) rather than a stopwatch reading of the round's actual elapsed time — the same reasoning this site's CPS test uses, so a repeat run at the same duration is always comparable to the last one.
  • Average time-to-hit is the mean, in milliseconds, of the interval between when each target became clickable and when it was hit. Both ends of that interval are read from event.timeStamp on real pointer events — the click that caused a target to spawn (the previous hit, or the Start button for the first target) provides the start, and the click that hits it provides the end. Deliberately not used: a requestAnimationFrame timestamp, because a frame callback fires once per paint and can lag behind the actual moment a click arrived by a frame or more, and Date.now(), which is not guaranteed monotonic. event.timeStamp is a high-resolution, monotonic value the browser attaches at the moment it receives the input — the closest available approximation of "when you actually clicked."

How the best-score logic works

The persisted "best" is the raw hit count for a round. Each mode-and-duration combination keeps its own entry in local storage — Flick/15s, Flick/30s, Grid/60s and so on are all tracked separately and never compared against each other — and a new result only overwrites the stored value when it is strictly higher than what was there before. A tie, a lower score, or an invalid/zero candidate all leave the stored best untouched.

How it was verified

The scoring functions are pure — no DOM, no timers — specifically so they can run under plain Node.js outside a browser. Before shipping, they were checked against fixed cases with known answers:

Verification cases and computed results
CheckInputExpectedResult
Accuracy8 hits, 2 misses80.0%match
Accuracy0 hits, 0 misses0.0%match
Targets/sec10 hits, 30s0.3333…match
Avg time-to-hit[100, 200, 300]ms200msmatch
Spawn bounds400×300 box, 22px radius, RNG at 0 and 0.999999centre stays within [radius, dimension − radius]match
Best-score updateprev 10, candidate 10no update (tie)match
Best-score updateprev 10, candidate 11updates to 11match

A degenerate case was checked too: if the play area were ever smaller than a target's diameter, the spawn function falls back to the centre of that dimension instead of producing a target that spawns partly outside the box or throwing an error.

How the site is built

  • Static HTML, one small stylesheet, two small scripts. No framework, no build step, no bundler. The pure scoring logic lives in one file and the DOM wiring — spawning targets, reading clicks, running the round timer — lives in a second file that depends on the first.
  • Nothing here needs the network. No CDN framework, no web font, no remote image; the favicon is an inline SVG data URI. Once loaded, the page keeps working offline.
  • System font stack. Your operating system's own UI font, so nothing has to download and nothing shifts as it loads.
  • What you click never leaves your device. The whole round runs in your browser; hit and miss events are never uploaded anywhere. The only thing written to storage is a best hit count per mode and duration, kept in your browser's own local storage.
  • Dark mode follows your system setting via prefers-color-scheme, and the target-spawn animation is skipped entirely when your system requests reduced motion — the targets still work exactly the same, they just appear without the pop-in effect.

Scope and honesty about limits

This measures target-acquisition speed and accuracy inside a browser tab, using whatever your operating system, browser and display report back — it cannot see or correct for your display's refresh rate, your mouse's polling rate, or general system load, all of which shift the numbers independently of your actual skill. See the caveat section on the main tool page for the specifics.

It also only tests stationary targets. It does not model a moving-target tracking drill, a specific game's sensitivity curve, hit registration, weapon spread or field of view, and it makes no claim to. It is a casual, general-purpose practice tool, not a verified benchmark or a substitute for practicing in whatever game you actually play.