Scrapstorm Squadron is a self-contained 2D up-scrolling fighter jet arcade game for the browser. It runs with a tiny zero-dependency Node webserver, uses generated bitmap game art, and can be deployed as a static Vercel project.
The game is built around a gritty retro military arcade style: a generated battlefield backdrop, generated sprite atlas graphics, chunky explosions, escalating enemy waves, powerups, wingmen, shields, bombs, and rotating boss aircraft.
npm run devThen open http://127.0.0.1:3500.
The local server reads these environment variables:
PORT: HTTP port, default3500HOST: bind host, default127.0.0.1
Example:
PORT=3000 HOST=127.0.0.1 npm run devnpm run dev
npm start
npm run checknpm run dev: start the local Node static servernpm start: start the same server for a generic Node hostnpm run check: syntax-checkserver.jsandpublic/game.js
- Up-scrolling top-down fighter jet combat
- Keyboard, mouse, and touch steering
- Automatic primary fire
- Bombs for screen-clearing pressure relief
- Regenerating shield and hull health
- Pickups for spread fire, lasers, rockets, shields, wingmen, bombs, repairs, magnet, and score boost
- Enemy scouts, heavy bombers, ace fighters, ground tanks, and boss aircraft
- Boss archetypes: dreadnought, gunship, and carrier
- Score combo multiplier that decays over time
- Status badges for active weapon level, timed powerups, rocket and wingman counts, and multipliers
- Generated battlefield background and generated sprite atlas graphics
- Layered Web Audio sound effects and arcade pulse music with a sound toggle
- Automatic pause when the window loses focus
- Move: arrow keys or WASD
- Bomb: space, B, X, or the bomb button
- Pause: P, Escape, or the pause button
- Launch or restart: Enter, the LAUNCH button, or the REARM button
- Sound: the SND/OFF button toggles audio
- Touch or mouse drag: steer the jet
The game pauses automatically when the browser window loses focus.
The heads-up display reads:
SCORE: zero-padded running scoreHULL: remaining hull healthSHIELD: regenerating shield chargeZONE: current zone, increasing with distance
Status badges appear above the HUD for active modifiers:
LV2-LV5: current weapon levelSPR: spread fire timerLSR: laser timerRKT: remaining rocketsWNG: active wingmenMAG: pickup magnet timerX2: score boostX1.x: active combo multiplier
The browser game supports lightweight demo query options for automated checks and visual review:
?demo=1: start gameplay automatically?demo=1&boss=1: start gameplay and spawn a boss encounter
Example:
http://127.0.0.1:3500/?demo=1&boss=1
Cache-busting query strings are used internally by public/index.html for game assets.
Runtime graphics live in public/assets/:
generated-battlefield.png: scrolling top-down battlefield backdropgenerated-sprite-atlas-alpha.png: transparent gameplay sprite atlas used by the renderergenerated-sprite-atlas.png: original chroma-key atlas source
The checked-in art is generated bitmap game art from gpt-image-2. The sprite atlas source uses a chroma-key background, and the runtime atlas is an alpha PNG derived from that source.
The sprite atlas includes player aircraft, wingman drones, enemy aircraft, tanks, boss aircraft, pickups, bullets, rockets, explosions, smoke, and muzzle flashes. public/game.js maps atlas regions to gameplay entities and falls back to procedural drawing only if an image asset is not available.
The canvas exposes non-visible data-* attributes for automated verification:
data-state: current game statedata-zone: current zonedata-shield: rounded shield valuedata-boss: active boss archetype, when presentdata-graphics: loaded generated graphics, such asatlas,battlefield
public/
assets/
generated-battlefield.png
generated-sprite-atlas-alpha.png
generated-sprite-atlas.png
game.js
index.html
styles.css
server.js
vercel.json
package.json
For Vercel:
vercel
vercel --prodThe vercel.json file points Vercel at public/, so the game deploys as static assets.
For a generic Node host:
npm startSet PORT and HOST if the host provides them. The server reads both automatically.

