LONGSHOT

Read the dossier. Find the silhouette. One shot.

Play itstickman.hobel.dev

LONGSHOT in play

Eight missions, each teaching exactly one new thing: aim and fire, then identification in a crowd, then travel time on a walking target, then crosswind, then masking a shot behind a passing tram, then leading a fast mover, then decoys in identical coats, then all of it at 520 m under fireworks.

Every dossier leads with a silhouette — a cane, a briefcase, a limp, a hood. Colour is only ever a confirming detail, never the thing that separates the target from the crowd. Zoom out to search, zoom in to shoot.

The reticle is in mils, not pixels, which is why a hold stays correct when you zoom: one mil always subtends range ÷ 1000 metres. A left-to-right wind pushes the round right, so you aim left — at 460 m a 3.5 m/s wind is worth about 1.4 mils, a bit over one body width.

Worth knowing

The negative tests are the point

A real browser plays all eight missions under the real production CSP and asserts that solved shots hit, that ignoring the wind misses, that ignoring the lead misses, that shooting a civilian or a decoy fails, and that an unmasked shot fails. A test that only proves you can win would pass just as happily if wind drift were zero and the crowd were scenery.

The rules never touch the DOM, so the tests import the real ones

Ballistics, scope sway, actor positions and mission adjudication are pure node-importable functions. The self-tests check the game's actual rules directly rather than a second implementation that can agree with itself while both are wrong. A separate check proves every mission's wind hold and lead is big enough to matter and small enough to fit in the scope, and that no target is separable from the crowd by colour alone.

About 21 kB gzipped, all of it first-party

Vanilla JavaScript and Canvas 2D with zero runtime dependencies — a 16 kB script, 2 kB of CSS, 3 kB of HTML. There are no image or audio assets anywhere: every stick figure is canvas path work and every sound is synthesised from oscillators at runtime.

Screens

Built with

Canvas 2DVanilla JSViteZero runtime dependenciesStatic bundle behind Caddy

Play LONGSHOT