# Isle Slingers — MODULES.md (master module list) the modularization pass. Folders = modules, subfolders = submodules. Every module and submodule carries an `agents.md` describing its surface and invariants. Load contract (order is load-bearing) is in `architecture.md` and encoded in `index.html` + `test/page.test.mjs`. | # | Module | Submodules | Public global | Role | |---|--------|-----------|---------------|------| | 1 | `js/physics/` | constants, state, aim, abilities, damage, step, collision, topple, rules, camera | `ISLE_CORE` (via `js/physics/index.js`) | Deterministic DOM-free physics engine (shared scope `P`) | | 2 | `js/levels/` | helpers, data (level-1..5) | `ISLE_LEVELS` `{LEVELS, SLING}` (via `js/levels/index.js`) | Level geometry + enemy/bird layouts (shared scope `L`) | | 3 | `js/audio/` | — (single file) | `ISLE_AUDIO` `{AudioEngine}` | Synthesized WebAudio SFX (no assets) | | 4 | `js/render/` | — (single file) | `ISLE_RENDERER` `{Renderer, VIEW_W, VIEW_H}` | Canvas drawing of the state object | | 5 | `js/app/` | — (single file) | page state on `window` | Input, screens/HUD, fixed-timestep main loop | ## physics submodules (shared scope `P`) | Submodule | Installs (into `P`) | Consumes from `P` | |-----------|--------------------|--------------------| | constants | WORLD, VIEW, MATERIALS, BIRD_TYPES, ENEMY_TYPES, GRAVITY, LAUNCH_POWER, MAX_PULL, MIN_PULL, AIR_DRAG, BIRD_BOUNCE, BIRD_GROUND_FRICTION, REST_SPEED, SETTLE_TIME, BIRD_MAX_AGE, ABILITY_CD, BIRD_BONUS | — | | state | createGame, makeBird, activeBird | WORLD, MATERIALS, BIRD_TYPES, ENEMY_TYPES, makeBird | | aim | aimVector, trajectory | LAUNCH_POWER, GRAVITY, AIR_DRAG, BIRD_BOUNCE, WORLD, BIRD_GROUND_FRICTION | | abilities | launch, triggerAbility | activeBird, aimVector, MATERIALS, BIRD_TYPES | | damage | damageBlock, damageEnemy | MATERIALS, ENEMY_TYPES | | step | step, stepPhysics, spendBird | (nearly all — the physics hub) | | collision | crushCircleVsBox, collideBirdWorld, collideBirdBlocks, collideBirdEnemies, REST_VEL_CLAMP, resolveBoxPair | MATERIALS, WORLD, damageBlock, damageEnemy | | topple | toppleBlocks, blockSupportSpan, beginTopple, integrateTopple, landTopple, topplePathDamage, settleBack, supportStillAlive | WORLD, GRAVITY, MATERIALS, REST_SPEED, damageBlock, damageEnemy, ENEMY_TYPES | | rules | checkEndStates, birdsRemaining, starsFor | — | | camera | updatePopups, updateCameraTarget, decayCamera | WORLD, VIEW | ## levels submodules (shared scope `L`) | Submodule | Installs (into `L`) | Consumes from `L` | |-----------|--------------------|--------------------| | helpers | wood, ice, stone, mogg, grum, king, SLING | — | | data/level-N | one level object each (returns it) | wood/ice/stone/mogg/grum/king, SLING | ## Physics notes (S-3/S-4/S-5, the physics + modularization update — landed 2026-09-29) - **topple** (S-3): blocks carry a rotational DOF (`ang`, `angVel`, `pivoting`). A resting block whose COM is past its support span pivots about the support-edge corner (full continuous rotation, Q1) and either lands on the ground (impact damage via `topplePathDamage`) or, if the pivot is too high to reach the ground, swings back and settles flat (`settleBack`, anti-livelock). - **collision** (S-4): crush is velocity-direction-aware (`boxAlong > 30` — falling boxes crush enemies from above or the side), per-enemy crush cooldown (0.12 s, one landing = one crush), and stacked block contact is mass-weighted so heavy blocks drive light planks (chain-crush). - **step** (S-5): a settled bird with another bird in play becomes `landed` (a live body under real gravity, no lifetime timer) and is integrated with the blocks; the last bird still spends (win/lose unchanged). `rules` must not declare `lost` while a landed bird is in the world. - **state** (S-3/S-5): block records carry `ang`/`angVel`/`pivoting`; bird records gain the `landed` state (queued | aiming | flying | landed | spent). ## Invariants (see architecture.md) - `ISLE_CORE` and `ISLE_LEVELS` public API surfaces are key-for-key stable. - Deterministic core: `createGame` + `step` are DOM-free and headless-safe. - Fixed timestep 1/120 s. Game is fully offline; no new runtime deps.