Three tiny battlefields, one turn-based grudge match.
A pocket-sized Advance Wars-style tactics game: move your knights onto the hex-ish grid, flank the spiders, slimes and crabs, and clear all three boards before you run out of turns. Originally built by Erik Onarheim as the Excalibur.js engine's official sample game; imported here as a BSD-2-Clause showcase of turn-based strategy on the platform.
Made by Erik Onarheim. Released under the BSD-2-Clause license — original source.
Changes for this platform: Removed the Google Fonts 'Material Symbols' stylesheet link (the only network call in the game) and replaced the mute button's icon-font glyphs with plain emoji text; stripped the og:/twitter: social meta tags and <link rel=canonical> that pointed at the original excaliburjs.com hosting and the matching unused res/ex-social.jpg + res/new-social.pdn art files. Removed the dead `LevelMusic1` resource ('Level 3.wav' from the Juhani Junkala pack, 14MB, over the platform's 8MB/file cap): it was loaded by the asset loader in upstream but never actually .play()'d anywhere, so the whole unused 48MB Juhani Junkala folder was dropped (verified with ffmpeg-static, since no system ffmpeg was present, that it does transcode cleanly to a 1.5MB OGG, in case it's ever wired back up). The two tracks that ARE played (res/gba1complete.mp3, res/two_left_socks.ogg, each ~3:15 and looped) were re-encoded to their first 45s with a 2s fade-out: decoding ~6.5 combined minutes of audio via AudioContext.decodeAudioData measured a real 7+ second stall before any content was interactive, which fails the platform's automated check's short scripted-play window and is bad UX generally; trimming cut that to ~1.5-2s load time and incidentally shrank both files 85%+. Set `suppressPlayButton: true` on the Engine (an official Excalibur option) to skip its own separate built-in 'Play game' click gate, which was stacking a second click-to-start screen in front of this game's own title screen and left ArcadeSDK.ready() uncalled within any reasonable test window. Called `game.useCanvas2DFallback()` since Excalibur's WebGL2 context isn't created with preserveDrawingBuffer, so any out-of-band canvas readback (screenshot diffing, cover-art capture) could see a blank buffer despite the game drawing fine on screen; this is a plain 2D sprite+text game, so Canvas2D has no visual cost. De-linked credits.html's external attribution links to plain text and dropped its Juhani Junkala credit line to match what's shipped; also noted the font it actually credits (NotJamSlabSerif11) is never @font-face'd anywhere — only NotJamSlab14.ttf, from the same CC0 'Not Jam' family, is used, so credits.html and CREDITS.md now name that file. Added a CSS reset for full-viewport fill on phones and locked the viewport meta against pinch-zoom. Added arcade-bridge.js for ArcadeSDK ready()/score()/gameOver()/onPause()/onResume() integration (pause via engine.clock.stop()/start() plus KeyP/Escape and a translucent overlay; KeyM mutes via the existing <audio-menu> element) backed by three one-line `window.__tt...()` call-outs in turn-manager.ts's three end-of-run branches and in main.ts. Progress (furthest level cleared) persists through ArcadeSDK.storage and resumes play at the right level on a later visit instead of replaying the tutorial every time. Score = levels cleared (0-3); gameOver fires with won:true on clearing level3 (the whole 3-level campaign), won:false on any level loss or turn-limit draw, since the game always lets you retry that level immediately after.
Comments 0
Log in to comment.