PURPOSE
Owns the sealed boss arena lifecycle: spawning a large circular (or rect) room centered on the player, shrinking it to its final size over a fixed duration, constraining the ship inside, culling entities that fall outside the wall, clearing terrain inside the footprint, locking the camera to the room, and rendering the wall against a pure-black void mask outside.
OWNS
BossRoomlifecycle state machine (closing→locked).- Ship-vs-wall positional clamp and velocity zero-out (with Rapier mirror).
- Per-frame entity cull (enemies, pickups, enemy bullets, player bullets) against the current room bounds.
- One-shot terrain clear inside the room footprint at spawn, including the Rapier static collider and the floater list, with spatial index rebuild after splices.
- Camera target clamp so the viewport never strays past the wall + margin.
- Wall rendering: black evenodd mask outside the rect arena, or a thick stroked ring for circles, plus the orange inner glow line.
READS FROM
coresingletons:game.time,ship(position, velocity, radius),world.enemies,world.pickups,world.enemyBullets,world.playerBullets,world.terrain,world.floaters,world.chunks,camera.zoom,camera.targetX/Y,W,H.CFG.BOSS_ROOM_INITIAL_SCALE,CFG.BOSS_ZOOM,CFG.BOSS_ROOM_SIZE_MULT,CFG.BOSS_ROOM_SHRINK_DURATION,CFG.BOSS_ROOM_MARGIN,CFG.BOSS_ROOM_WALL_THICKNESS.RapierWorld.isReady()to gate physics-side mutations.- Enemy flags
isBoss,sharesHealthWithBoss,_isBossAnchorto exempt boss-system entities from the cull.
PUSHES TO
ship.x/y/vx/vy(clamp and velocity cancel along the wall normal).RapierShip.teleportKeepVelocity+RapierShip.setLinvelto mirror clamps into the physics world.world.enemies[i].alive = falsefor non-boss enemies outside the room.world.pickups,world.enemyBullets,world.playerBullets: swap-and-pop removal of out-of-bounds entries.world.terrain,world.floaters: splice removal of pieces inside the footprint, with matchingRapierTerrain.removePiece/RapierTerrain.removeFloatercalls.buildTerrainChunks(world)to rebuild the spatial index after terrain splices.camera.targetX/Yclamp.- Canvas drawing commands on the supplied
CanvasRenderingContext2D.
DOES NOT
- Spawn the boss itself or drive boss AI (the encounter module owns that).
- Read or apply biome / backdrop drawing; the wall renderer just masks them with black.
- Manage XP orbs — those live in SoA storage and self-cull in
xp-orbs.ts. - Persist any state outside the returned
BossRoomobject. - Run physics steps; it only teleports the ship body and removes terrain colliders.
Signals
room.statetransitionclosing→lockedwhen the shrink ease reachest = 1.enemy.alive = falsewrites are the only signal emitted to gameplay; downstream death/loot is handled by the main update loop.
Entry points
spawnBossRoom(def)— constructs theBossRoomat ship position with the configured initial scale, computestargetRfrom viewport, boss zoom, andBOSS_ROOM_SIZE_MULT, clears terrain inside the final footprint, returns the room.updateBossRoom(room, dt)— per-frame: tracks player while closing, eases the shrink witheaseInOutQuad, transitions tolocked, constrains the ship, runs the entity cull (every frame while closing, every third frame once locked).clampCameraToRoom(room)— call afterCamera.update()to keepcamera.targetX/Yinside the room + margin.renderBossRoomWalls(ctx, room)— draws the void mask and wall outline; circle path strokes a thick ring, rect path uses an evenodd-fill black mask plus inner stroke.
Pattern notes
- Circle arena is the primary shape; rect paths exist as a fallback for
room.shape === 'rect'and the terrain clear uses a square footprint of sidetargetWso a rect spawn still works. - Initial radius is
max(W, H) * 0.4 / bossZoom * BOSS_ROOM_SIZE_MULT, sized so the closing ring is fully visible on portrait phones. - Shrink curve is
easeInOutQuadoverBOSS_ROOM_SHRINK_DURATION. The room starts atBOSS_ROOM_INITIAL_SCALEtimes target. - During
closing,cx/cytrack the ship so the arena collapses around it; onlocked, they freeze. - Entity cull is intentionally branch-light: bounds are lifted to locals,
outside()switches on shape once, swap-and-pop avoids array shifts. Cull is throttled to every third frame once the wall is static. - Enemies marked
isBoss,sharesHealthWithBoss, or_isBossAnchorare exempt from the cull because boss anchors are placed at fixed arena-relative positions and the shrinking ring would otherwise destroy shielded / shielded_respawn / periodic_invuln affixes. - Ship clamp uses
ship.outerRadius || ship.radius || 14for the wall offset. Velocity is zeroed along the wall normal (rect: per-axis; circle: dot-product projection). Rapier teleport + linvel set keeps the physics body in sync. - Terrain clear uses an oversized circular bound (
targetR * 2) to ensure pieces straddling the edge are removed. After splicing, the spatial index inworld.chunksis rebuilt ornearbyTerrain()andpushOffTerrainwill dereference stale indices. - Camera clamp first checks whether the arena is wider than the viewport; if not, it pins to the room center on that axis instead of clamping.
- Rect wall rendering composites a fullscreen black rect with the arena rect cut out using
evenoddfill — purely visual, the Rapier wall colliders still sit atSEALED_ARENA_WALL_THICKNESSextents. - Module-level
_cullTickcounter is the only mutable state outside theBossRoomobject.