Skip to content

Releases: drsamonline/eon-commando

Eon Commando 3.0.0 — endless mode

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 07:33

Endless mode is in, and the title screen is a real menu.

Endless

How it plays

The camera locks, the gate shuts, and hostiles arrive from both sides and from above. Wave one is two grunts. The pool widens as you go — drones, then jumpers and snipers, then swarms and shielders, then turrets and brutes — and the crowd keeps growing. Every fifth wave adds a boss from the campaign rotation, on top of the crowd.

The multiplier is the point. Each wave adds 0.15× to your score — wave seven pays 1.90×. Dying is the only way a run ends, so every wave asks the same question: push one more? You also get a grenade back per wave cleared, so a long run has a resource rhythm rather than just attrition.

The title screen had to change first

Endless needed an entry point, and a keyboard-only E key would have repeated exactly the mistake I'd just fixed on mobile. So the title is now a menu — Campaign, Endless, Daily Run, Watch Last Run, Two Players — navigable with arrows or by tapping. The Two Players toggle replaces "press 2".

One bug worth naming

A boss dying in endless called the campaign boss-death handler, which fired the stage-clear sequence and would have dropped you into era two mid-run. Game.mode now gates that: in endless a boss death just ends the wave.

Also caught: the title still said V2.3.0 — the single VERSION constant I introduced two releases ago to stop exactly this had itself never been bumped. It reads 3.0.0 now.

Numbers

Game index.html — 178 KB, single file
Gzipped 49 KB
Enemy types in the pool 9, unlocked by wave
Boss cadence every 5 waves
Dependencies 0

Full notes in CHANGELOG.md.

Eon Commando 2.8.0 — auto-fire

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 06:13

Auto-fire is in, and it's on by default on a touch screen.

Holding a fire button while steering with the same thumb was the worst part of this game on a phone. The autoFire setting existed in the menu since 2.0 but was wired to nothing — it did nothing at all. Now it works.

It aims for you, it does not decide for you

Auto-fire engages a target only within ~31° of where you are already pointing and within 210 px. Point up and it shoots up; point the diagonal and it shoots the diagonal; anything behind you is ignored. The shot goes to the acquired angle while the arm swings toward it for looks — so the assist corrects precision, not intent. Manual fire on Z/B still overrides it.

On by default for touch, off for keyboard, decided on first run. AUTO shows next to the weapon and brightens when a target is locked.

It made the phone view better too

With aiming handled, a closer camera became viable — so portrait tightened from 270 to 220 world pixels wide. The commando is now 21 px wide instead of 17, and the play area covers 57% of the screen height instead of 46%. That's the answer to "it's small" that I couldn't reach before without making the game unfair.

Replanned order for what's left

I've rewritten the roadmap in the README. Shipped: three eras, nine enemy types, three bosses with hazards, dash/melee/grenades, co-op, difficulty tiers, accessibility, widescreen and portrait, 573 draw ops/frame, replays, daily seeds, rebinding, touch menus, auto-fire, PWA.

Remaining, in the order I'd build them:

  1. Endless mode — escalating waves on the existing arenas, score multiplier, no new art. Three stages is thin for a run-and-gun and this is the biggest content win available; it also gives the difficulty tiers and replays far more to chew on.
  2. Touch pad layout editor — drag the pads anywhere, per device. The last real mobile gap.
  3. Perks between eras — pick 1 of 3, now that difficulty tiers exist to hang them on.
  4. Android APK / Windows EXE through app-builder.
  5. LAN co-op through lan-kit.

Numbers

Game index.html — 174 KB, single file
Gzipped 47 KB
Portrait commando 21 px wide, up from 17
Play area on a phone 57% of screen height, up from 46%
Dependencies 0

Full notes in CHANGELOG.md.

Eon Commando 2.7.0 — menus on touch

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 06:08

The menus work on a phone now. Until this release, everything past the title screen assumed a keyboard — a touch player could start a run and never reach settings, controls, or restart.

Pause on a phone

Pause is a real menu

Resume / Settings / Controls / Restart Run / Quit to Title. Reachable from the ❙❙ button, navigable by tap or arrow keys.

Every menu is tappable

Pause, Settings and Controls build a hit-map as they draw, so what you see is exactly what responds — the layout and the touch targets can't drift apart the way hand-maintained hit boxes do.

Settings rows respond to position: tap the right half to increase, the left half to decrease. No hunting for an arrow button. Keyboard and tap share one nudgeSetting() so the two paths can't diverge.

Sized for fingers

Pause rows step 25 px apart in portrait — about 36 px on a 390-wide screen — instead of 18, and every menu's hit band is wider than its text. My first pass shipped 23 px rows, which looks fine and taps badly.

Two bugs found on the way

fitCanvas computed the portrait view height after the screenshot early-return, so ?shot=1 on a phone silently rendered the old 16:9 layout. The mobile screenshot in this release was wrong before I caught it — the harness showed a 390×390 canvas where it should have been 390×844.

And the HUD's era banner overlapped the pause menu, because the HUD was still drawing behind it.

Still true

Rebinding is keyboard-only, and the touch pads are fixed-position. But you can now reach the settings that matter on a phone, which you could not before.

Numbers

Game index.html — 171 KB, single file
Gzipped 47 KB
Screen fill 100% × 100% at every viewport
Dependencies 0

Full notes in CHANGELOG.md.

Eon Commando 2.6.0 — rebindable controls

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 06:01

Every key is rebindable, per player, and it sticks.

Controls

Settings → Controls (O, then Enter). Up/down picks an action, Enter starts listening and the next key you press is bound, R resets that player, left/right switches between player one and player two.

The interesting part

Bindings used to be two hardcoded keycode maps. They're now a data table per player, persisted in localStorage, with a reverse map rebuilt on every change. That matters for three reasons:

  • Binding a key steals it. Bind Q to fire and Q is removed from whatever else used it — the previous owner falls back to its default rather than silently becoming unbound. That's the failure mode most rebinding screens ship with.
  • Player two is rebindable too. WASD + , . / ; ' are now defaults, not a hardcoded second map, so co-op follows your bindings.
  • Gamepad flows through the same table, so a future pad-rebind is a UI change, not an engine change.

Verified end to end: rebinding jump to Q makes X stop jumping and Q start; the change survives a save/reload; stealing works both directions; reset restores defaults; player two's bindings stay independent of player one's.

Not done, deliberately

On-screen touch buttons are still fixed-position. Rebinding covers keyboard and gamepad. A touch layout editor — drag the pads anywhere, per device — is a separate job and a bigger one, because it needs its own persistence and a preview. I'd rather ship keyboard rebinding now than half of both.

Numbers

Game index.html — 167 KB, single file
Gzipped 46 KB
Rebindable actions 9 per player, 2 players
Dependencies 0

Full notes in CHANGELOG.md.

Eon Commando 2.5.0 — replays and daily runs

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 05:57

Replays and a daily run — both local, both offline.

The simulation is deterministic: same seed plus same inputs produces the same run, exactly. So a replay doesn't record game state at all — just the seed and the input stream.

Replays

R on the title replays your last run, with a REPLAY watermark.

900 frames of play compress to 196 characters of run-length-encoded text in localStorage, because input is mostly static frame to frame. Verified rather than assumed:

recorded  score 1380 · x 861 · 210 · 1 · 8 · era 0 · lives 2
replayed  score 1380 · x 861 · 210 · 1 · 8 · era 0 · lives 2   MATCH: YES

That's the whole run reproduced frame for frame from 196 characters.

Daily run

D on the title seeds a run from today's local date, so everyone playing today gets the same run. No server, no clock sync, no leaderboard — just the date hashed into a seed. Today it's 834542573, labelled 1/11 on the title screen.

Why this was only possible now

Replays need determinism, which needed the seeded sim/fx RNG split from 2.3 and the cosmetic-randomness fix that came with it. Without those, a replay would drift within seconds. This is the payoff for that unglamorous work.

Numbers

Game index.html — 162 KB, single file
Gzipped 44 KB
Replay size 196 chars for 900 frames
Playback fidelity Exact
Dependencies 0

Full notes in CHANGELOG.md.

Eon Commando 2.4.0 — phones use the whole screen

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 05:49

Portrait was using a quarter of your screen. That's fixed — and I measured it rather than guessing.

Before: on a 390×844 phone the canvas was 390×219 — 26% of the height, sprites tiny.
After: 390×390 — 46% of the height, 78% larger.

What was wrong

The view was forced to 16:9 in both orientations. A 16:9 band on a phone held upright can only ever be a strip, no matter how you scale it. Portrait now uses a square logical view (270×270) and the canvas takes the full screen height.

The layout

The play area sits at the top where your eyes are, the earth continues below it with strata and grit, and the thumb pads overlay that lower band — so nothing is wasted and nothing overlaps the action. Sky above, ground in the middle, dirt under your thumbs.

Measured fill, now 100% of both axes at every size I could test: 390×844, 360×640, 412×915, 768×1024, 844×390, 640×360, 1440×810. Landscape was already full and stays full.

Three things this broke, all fixed

  • The title screen overflowed a 270-wide view — the control lines, the start prompt and the version string ran off both edges. Shorter copy below 380 px wide.
  • The settings screen overflowed the same way; rows and footer reflow now.
  • Bosses could walk off screen, because the arena is a fixed 480 wide but a portrait view is 270. Boss movement is clamped to the visible window — verified at 270 wide with the boss centred at x=135 of 270.

Honest limit

A 270-tall world can occupy at most 390×390 on a 390-wide phone. That's geometry, not laziness — to fill more you'd have to show less width than the player needs to see incoming fire. If you want the widest view, rotate: landscape shows 584 world pixels against portrait's 270, which is why the rotate hint is still there.

Numbers

Game index.html — 156 KB, single file
Gzipped 43 KB
Portrait play area 390×390 on an iPhone, up from 390×219
Screen fill 100% × 100% at every viewport tested
Dependencies 0

Full notes in CHANGELOG.md.

Eon Commando 2.3.0 — 74% fewer draw calls

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 05:38

74% fewer draw operations per frame — 2,210 down to 573. Same pixels, a quarter of the work.

I measured this by instrumenting the canvas context and counting calls, not with a stopwatch. That matters: my first stopwatch runs said the ground baking was 30% faster, then the same build measured slower on a re-run. Headless frame timing is noisy enough to lie to you, so I switched to counting operations, which is deterministic.

What actually cost the time

Not the ground — the legacy path already culled to the viewport, so baking it saved only 235 ops. The surprise was text: every HUD string was drawn as dozens of fillRect glyphs per frame, and the score alone was ~1,400 of the 2,210 operations. Caching each unique string into a small canvas and blitting it did most of the work.

  • Ground baked into 1024 px chunks — floor, strata, rim light, 1,100 speckles and every prop rendered once. The old path stays behind ?legacyground=1 so you can compare: they match to within one pixel on 0.24% of pixels (sub-pixel rounding where chunks meet).
  • HUD text cached by string, scale, colour and shadow.
  • Broad-phase bullets skip enemies they can't reach before doing box maths.

New tools you can use

Flag What it does
?fps=1 Overlay: fps, frame ms, entity counts
?bench=600 Times 600 update+render pairs, prints the average
?seed=4242 Pins the run seed — reproducible end to end
?legacyground=1 Draws the floor the old way, for comparison

?seed also makes runs reproducible for replays: cosmetic randomness (rnd, pick, chance) now routes through the seeded fx stream instead of Math.random.

Two bugs found on the way

Props taller than the ground line were clipped out of the baked chunks, and the chunk gradient was mapped across the wrong band, tinting the whole floor. Both only showed up because I diffed the baked render against the live path pixel by pixel — neither would have been obvious to the eye on a dark stage.

Numbers

Game index.html — 153 KB, single file
Gzipped 42 KB
Draw ops/frame 573, down from 2,210
Dependencies 0
Network requests 0

Full notes in CHANGELOG.md.

Eon Commando 2.2.0 — arena hazards and weak points

Choose a tag to compare

@drsamonline drsamonline released this 01 Nov 05:22

Bosses are no longer a scripted loop. Each one now has three attacks on separate clocks, plus arena hazards and a weak point.

The Warden drops the ceiling on you

Debris

Three rocks (five in phase 2) land on your position, each telegraphed for 42 frames by a shadow on the ground and a falling marker line. You always know exactly where not to stand.

The Eon Heart sweeps the arena

Beam

A 70-frame dashed telegraph, then 150 frames of live beam rotating across the arena. Phase 2 sends two, counter-rotating.

The Glacier Wraith calls for help

Two swarm darts per wave on its own timer, separate from its ice-shard fan. Kill them or eat them.

A weak point that rewards aiming

The Warden's core takes double damage — a body shot does 4, a core shot does 8, with a CORE popup when you find it. Bosses stop being "hold fire at the biggest rectangle on screen".

Every hazard is a real entity with its own telegraph, damage box and lifetime, so they work in co-op and can be dodged with the dash's i-frames.

A bug worth naming

The Wraith's summon timer and the Heart's beam timer were nested inside another attack's handler, so they only ticked on the frames that attack fired. The beams in particular almost never appeared — the code looked right and the screenshots looked fine, because the attack it was hiding inside still worked. The assertion caught it. Both now run on their own clocks.

Numbers

Game index.html — 147 KB, single file
Gzipped 40 KB
Dependencies 0
Network requests 0

Full notes in CHANGELOG.md.

Eon Commando 2.1.0 — local co-op

Choose a tag to compare

@drsamonline drsamonline released this 31 Oct 21:43

Two players, one screen, no network. Press 2 on the title screen.

Co-op

Player one takes the arrows and Space/Z; player two takes WASD and , . / ; '. A second gamepad is picked up automatically as player two.

Shared screen

  • The camera frames both players from their midpoint
  • A soft leash nudges a straggler back into view at 3 px a frame — no teleporting, no rubber-band snap

Down and revive

  • At zero health you go down for six seconds instead of dying
  • A partner standing within 26 px for about a second revives you at one heart, with a progress ring around your body
  • Nobody reaches you and you bleed out
  • A life is only lost when nobody is left standing — both down means the run restarts at the last checkpoint together

Enemies notice you both

Turrets, grunts, snipers and every boss target whichever commando is nearest. Contact damage is checked against both players, and pickups go to whoever touches them first.

Three bugs the test harness caught

  • Downed players fell through the floor. Gravity applied but collision did not, so a downed body dropped into the void and revive could never trigger. It was invisible in a screenshot and obvious in an assertion.
  • The co-op leash teleported players to the screen edge instead of pushing them.
  • The brute's shoulder charge fired whenever it was within 70 px, which read as relentless rather than deliberate. It now telegraphs for 14 frames and sits on a 150-frame cooldown.

Numbers

Game index.html — 141 KB, single file
Gzipped 38 KB
Dependencies 0
Network requests 0

Full notes in CHANGELOG.md.

Eon Commando 2.0.0 — dash, melee, grenades, nine enemies

Choose a tag to compare

@drsamonline drsamonline released this 31 Oct 21:33

The biggest release yet: three new verbs, four new enemies, difficulty tiers, an accessibility settings screen, and the game is now installable.

New verbs

Key Action
Shift Dash — 10 frames, invulnerable, short cooldown, with afterimages
V Melee — a 19 px arc in front of you, 3 damage, 3 frames of hit-stop
G Grenade — three per life, arced, bounces, 5 damage in a 42 px radius

All three have touch buttons. The gun is no longer your only answer.

Four new enemies — nine archetypes in total

Sniper paints a laser sight on you for 42 frames before firing. Swarm darts fly straight at your face. Brute is armoured, heavy, and shoulder-charges at close range. Shielder carries a front plate that stops your bullets dead — you have to flank it or jump over it.

Every shooter now telegraphs for 16–42 frames before it fires, so a death is something you could have read.

Hit-stop that does not eat your inputs

Three frames of frozen world on melee and grenade hits. The world stops, you do not — a grenade press during the freeze is still a grenade. (My first attempt froze everything and silently swallowed the input; caught it in testing and fixed it.)

Difficulty tiers

Recruit — 6 hearts, 5 lives, half damage taken. Commando — the game as it was. Eon — 2 hearts, 1 life, 1.5× damage, tougher enemies, fewer drops.

Settings and accessibility

Settings

Press O or open it from pause: difficulty, colour scheme, reduce motion, flash intensity, HUD size, music, sound effects, auto-fire. Everything persists.

The colour schemes include deuteranopia and high contrast, and they recolour hostile fire — the thing that actually matters in a bullet-hell moment. Reduce-motion kills shake, flashes and scanlines. Flash intensity is a slider, for photosensitivity.

Platform

  • Installable — manifest.json and a service worker ship beside the game; install once, launch with the network off
  • DPR-aware backbuffer (capped 2×) for sharp pixels on retina
  • Fullscreen on F, and a screen Wake Lock while you play
  • Local leaderboard — top five runs on the title screen, plus lifetime stats
  • Seeded RNG split into sim and fx streams, so gameplay is reproducible

Numbers

Game index.html — 133 KB, single file
Gzipped 36 KB
Dependencies 0
Network requests 0

Full notes in CHANGELOG.md.