TinyGames · how it works

Talon

A vertical shooter with a hangar between missions. Fly, shoot, bank the bounties, buy a bigger gun, fly again.

Open index.html. No build step, no dependencies, no images.

talon/
  index.html         markup
  style.css          the frame around the canvas
  js/engine.js       copied unchanged from Overdrive - the sixteenth game on it
  js/patterns.js     bullet patterns, enemies, missions and the shop
                     - no pixels, no engine, no DOM
  js/talon.js        the playable layer
  test-patterns.js   node test-patterns.js

Every pattern is proved dodgeable

A bullet pattern that covers every square the player could reach is not difficult, it is broken — and by eye it is indistinguishable from one that is merely hard, so playtesting will not find it.

So patterns here are pure functions from (source, target, phase) to a list of bullets, with no reference to the world. That makes them cheap to fire thousands of times in a test and ask, for each firing: was there anywhere the player could have been standing, and could have reached in time, that this pattern does not cover?

$ node test-patterns.js

  can it be dodged:
    single   900 firings   narrowest escape  58 of 61 places   always dodgeable
    twin     900 firings   narrowest escape  57 of 61 places   always dodgeable
    fan      900 firings   narrowest escape  38 of 61 places   always dodgeable
    burst    900 firings   narrowest escape  33 of 61 places   always dodgeable
    lance    900 firings   narrowest escape  58 of 61 places   always dodgeable
    barrage  900 firings   narrowest escape  31 of 61 places   always dodgeable

73 passed, 0 failed

And the check can say no. Otherwise the result above is vacuous. The suite fires a rank of 200 bullets across 2,000 pixels — dense enough that there is no room between two, wide enough that you cannot run round the end — and confirms it is reported inescapable 50 times out of 50. Then it punches one hole in the same wall and confirms it becomes escapable 50 out of 50. It is the gap doing the work, and the test proves that rather than assuming it.

The horizon was making it vacuous

The first version used a fixed 2.2-second window. Slow bullets fired from the top of the screen never reached the player inside it, so every one of those firings was declared safe because nothing had arrived yet. It is now derived from the slowest bullet and the distance it has to cover.

That is also why the Dreadnought's barrage — a wall with a single hole in it, placed away from where you are standing so it has to be flown to — is in the game at all. It is the one pattern that would be unfair without care, and the test is what says it is not.


Two things measurement changed

Enemies were scenery that shot at you. At the first speeds a drone crossed the screen in under five seconds, and a measured bot banked 11% of a mission's value — the rest simply flew past. Speeds are roughly halved now.

That barely helped, which was the useful part. The real constraint was never speed, it was that one narrow gun cannot reach six to nine targets spread across the screen before they are gone. Wave counts are halved and bounties doubled: a mission is worth the same, but each enemy is something you can go and kill. Capture went from 11% to 18%, and the first upgrade now lands after a mission or two.

The shop ladder is tested against that measured rate, not against full capture. Pricing it as though you kill everything would mean upgrades that in practice never arrive.


Income and difficulty are different curves

Wave counts step rather than climb smoothly, so two missions running can pay the same — while the health multiplier rises every single mission. A mission can therefore be harder than the last without paying more.

The tests assert them separately: threat strictly climbs every mission, pay never falls and never stays flat for more than two. The first version asserted strict growth on the bounty total and failed, blaming the wrong number for a difficulty curve that was working perfectly well.


Controls

Drag the ship follows your finger
/ WASD fly
the gun fires by itself
15, H buy in the hangar
Space launch
R new run

The ship goes exactly where you point rather than being dragged relative to your finger, and there is no trigger — anything needing a second thumb costs you the half of the screen you most need to see. A tap far from the ship snaps it over rather than doing nothing.


The hangar

Five guns and four hulls. The tests hold the table to properties rather than to numbers: each gun costs more and does more than the last, the best is more than three times the first, hulls get tougher and dearer in step, and — the one that matters — the whole ladder is reachable inside thirty missions at a realistic capture rate, with the first upgrade early and the last one earned.


Things deliberately left undone