# Monsterplex A Trials-style physics driving game starring a school bus, crossed with Snuggle Truck: land badly enough and the g-force throws your passengers off. Built with **Phaser 4**, plain **ES6 modules**, and **no package manager**. ## Running it Browsers block ES module imports over `file://`, so serve the folder with any static file server. No install needed - this ships with Python 3: ```sh python3 -m http.server 8000 ``` Then open `http://localhost:8000/`. ## Controls - **Arrow Up / W** - throttle - **Arrow Down / S** - brake / reverse - **Arrow Left/Right / A/D** - lean the bus left/right Land smoothly or the g-force throws a kid off the bus. Lose all of them and the level fails. ## Project layout ``` index.html entry point, import map -> vendor/phaser.esm.js vendor/phaser.esm.js vendored local copy of Phaser 4 (see below) src/main.js Phaser.Game config + scene list src/config.js every tunable constant (physics, g-force threshold, camera, ...) src/scenes/ Boot -> Preload -> Intro -> MainMenu -> LevelSelect -> Play -> LevelComplete/LevelFailed src/entities/ Bus, Kid, Terrain src/systems/ GForceMonitor, KidManager, InputController, CameraRig src/data/levels/ the 3 hand-authored levels src/util/ asset manifest, placeholder-texture generator, localStorage progress, small UI helper assets/ where real art goes (see manifest below) - currently empty ``` ## Adding real art No art assets exist yet - `src/util/assetManifest.js` lists every image the game expects, and `PreloadScene` falls back to a synthesized colored placeholder (via `src/util/placeholderTextures.js`) for anything missing. **Drop a real PNG at the exact path below and it's picked up automatically - no code changes needed.** | key | path | size | notes | |---|---|---|---| | `bus_chassis` | `assets/sprites/bus_chassis.png` | 170x64 | scaled to this size regardless of source resolution | | `bus_wheel` | `assets/sprites/bus_wheel.png` | 52x52 | used for both wheels | | `kid_idle` | `assets/sprites/kid_idle.png` | 28x28 | passenger while aboard | | `kid_ejected` | `assets/sprites/kid_ejected.png` | 28x28 | passenger after being thrown off | | `bg_far` | `assets/backgrounds/bg_far.png` | 256x540 | tiled, slowest parallax layer | | `bg_mid` | `assets/backgrounds/bg_mid.png` | 256x540 | tiled, mid parallax layer | | `bg_near` | `assets/backgrounds/bg_near.png` | 256x540 | tiled, fastest parallax layer | | `icon_kid` | `assets/ui/icon_kid.png` | 24x24 | HUD "kids aboard" icon | | `favicon` | `assets/favicon.png` | 32x32 | browser tab icon | ## Tuning the feel Everything worth tweaking lives in `src/config.js`, notably: - `GFORCE.ejectThresholdG` - how hard a landing has to be before a kid is thrown off. Not physically derived - tune by playtesting. - `GFORCE.gracePeriodMs` / `ejectCooldownMs` - ignore-window after level start/restart, and minimum time between two ejections so one bad landing doesn't empty the whole bus at once. - `BUS.*` - suspension stiffness/damping, wheel friction, throttle/lean torque and their clamps. Set `DEBUG = true` in `config.js` to show a live g-force readout and Matter's physics debug overlay in `PlayScene`. ## Phaser 4 loading Phaser is vendored locally at `vendor/phaser.esm.js` (downloaded once from jsDelivr's CDN build) and wired up via an import map in `index.html`, so every source file just does `import Phaser from 'phaser'` like a normal npm project would - the only place that knows about the vendored file is that one import map line. This keeps the project working fully offline with no runtime dependency on a third-party CDN staying up. To upgrade Phaser later: download a newer `phaser.esm.js` build over `vendor/phaser.esm.js` and re-verify `Bus.js` against the Matter physics Factory API in the new file (grep for `class Factory` under the Matter section).