A mobile-first offline PWA roguelite prototype inspired by the upgrade-synergy chaos of games like 20 Minutes Till Dawn.
https://mateocabanal.github.io/midnight-engine/
The current target is a full 20-minute Dawn Run:
- Pick a character and weapon.
- Move, aim, fire, reload, and trigger character active abilities.
- Collect XP gems, level up, and draft upgrade paths/fusions/laws.
- Survive escalating director phases: Opening Dusk, First Swarm, Elite Hunt, Bullet Hell, Night Terror, and Final Dawn.
- Fight distinct enemy archetypes: husks, runners, brutes, spitters, chargers, elites, and boss bells.
- Win by surviving until dawn or lose with Engine Collapsed.
- Review the run summary and quickly restart.
Local progress is stored in localStorage: selected loadout, best survival time, best kills, highest level, victories, and discovered character/weapon pairings.
- Director phases:
directorPhasesinsrc/game.tscontrols spawn interval, pack size, threat, elite cadence, and enemy mix across the 20-minute run. - Boss cadence: miniboss bells appear at 5, 10, and 15 minutes, with the final Dawn Bell entering during the last minute.
- Enemy archetypes: runners pressure movement, brutes anchor swarms, spitters add bullet-hell projectiles, chargers create dodge checks, elites drop higher-value XP, and bosses fire radial patterns.
- Draft controls: level-up cards support rarity/category tags, rerolls, banishes, and skip-for-heal/shield.
- Synergy drafting: choices are weighted by rarity, prerequisite readiness, character strengths, and previous draft exposure.
- Declarative sprites: players, enemies, bullets, summons, and pickups are data-driven through
spriteCatalogandgetSpriteDefinition().
- Left stick: move.
- Right stick: aim and fire.
- Active button: trigger the selected character ability when ready.
- Landscape orientation is recommended for twin-stick play.
WASDor arrow keys: move.IJKL: aim and fire in a direction.SpaceorEnter: fire in the current aim direction.EorShift: trigger active ability.
npm install
npm run dev
npm run typecheck
npm test
npm run build
npm run preview
npm run e2enpm run devstarts the Vite dev server.npm run typecheckruns TypeScript without emitting files.npm testruns deterministic Vitest game-core coverage.npm run buildcreates the production PWA bundle.npm run previewserves the production build locally.npm run e2eruns the Playwright browser smoke test against the built preview.
The GitHub Pages workflow deploys from main or master. CI installs with npm ci, then runs:
npm run typechecknpm testnpm run buildnpm run e2e
Only a passing build artifact is uploaded to GitHub Pages.