Go to file
Brian Fertig 9892df762c Rework ejection feel, parallax backgrounds, and camera bounds
- Ejection: drop GFORCE.ejectThresholdG from 6 to 0.5 - the bouncier
  suspension isolates the chassis from shock, so the old threshold was
  effectively unreachable and kids were never actually being ejected.
  Ejected kids now pop straight up through the roof (ignoring chassis
  velocity/tilt) and fly under a lighter gravity (KID.ejectedGravityScale
  0.35, applied via KidManager's beforeupdate handler) for a floaty,
  Snuggle-Truck-style arc.
- Cut maxLeanAngularVelocity and leanTorqueStep in half for a slower,
  more gradual lean that's easier to fine-tune mid-air.
- Parallax: far layer is now screen-fixed, scaled uniformly (no stretch),
  and pans exactly once from start to goal by level progress; mid/near
  layers are bottom-anchored and tiled at their own uniform scales. Kids
  render at depth -1 so the bus always draws over them.
- Level builder: size camera bounds to the level's actual terrain min/max
  Y (with padding, 1000px floor) instead of a fixed 1000 height, so long
  runs of declines no longer push the bus below the camera's reach.
- Add level 04 "Mega Drop" (5 kids, extended terrain ending in the mega
  drop sequence).
2026-08-19 20:58:01 -06:00
assets Add level editor and retune physics/camera for bouncier, floatier driving 2026-08-19 20:07:24 -06:00
src Rework ejection feel, parallax backgrounds, and camera bounds 2026-08-19 20:58:01 -06:00
vendor Initial Commit 2026-08-18 20:23:33 -06:00
README.md Initial Commit 2026-08-18 20:23:33 -06:00
editor.html Add level editor and retune physics/camera for bouncier, floatier driving 2026-08-19 20:07:24 -06:00
index.html Initial Commit 2026-08-18 20:23:33 -06:00
sprites.md Initial Commit 2026-08-18 20:23:33 -06:00
start_web.sh Initial Commit 2026-08-18 20:23:33 -06:00

README.md

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:

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).