/* ISLE SLINGERS -- physics/camera/index.js (submodule: camera) * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that * attaches the public ISLE_CORE API). Surface installed: updatePopups, updateCameraTarget, decayCamera. */ (function (root, factory) { var part = factory(); if (typeof module !== 'undefined' && module.exports) module.exports = part; else (root.ISLE_PHYSICS_PARTS = root.ISLE_PHYSICS_PARTS || []).push(part); })(typeof globalThis !== 'undefined' ? globalThis : this, function () { 'use strict'; return function (P) { P.updatePopups = function(g, dt) { for (var i = g.scorePopups.length - 1; i >= 0; i--) { g.scorePopups[i].age += dt; g.scorePopups[i].y -= 40 * dt; if (g.scorePopups[i].age > 1.4) g.scorePopups.splice(i, 1); } } P.updateCameraTarget = function(g) { var b = P.activeBird(g); var cam = g.camera; var tx, ty, tz; if (b && b.state === 'flying') { // in flight: follow the slinger 1:1 (the bird IS the point of interest) tx = Math.max(420, Math.min(P.WORLD.w - 420, b.x + 220)); ty = Math.max(380, Math.min(P.WORLD.ground - 160, b.y + 60)); tz = 1; } else { // aiming / waiting: frame the slingshot AND the whole action zone // (live blocks + enemies) so P.launch point and target are always // visible at once — zooming out when the level needs it. Without // this the sling was visible but the fort was off-screen (or // vice-versa mid-flight), making aiming pure guesswork. var left = g.level.sling.x - 190; var right = left + 300; for (var i = 0; i < g.blocks.length; i++) { var bl = g.blocks[i]; if (bl.hp > 0) right = Math.max(right, bl.x + bl.w / 2 + 90); } for (var k = 0; k < g.enemies.length; k++) { var en = g.enemies[k]; if (!en.dead) right = Math.max(right, en.x + en.r + 90); } var span = right - left; tz = Math.min(1, P.VIEW.w / span); tx = left + span / 2; // ground at ~78% down the view, whatever the zoom ty = Math.max(300, Math.min(P.WORLD.ground, P.WORLD.ground - (0.28 * P.VIEW.h) / tz)); } if (cam.snap) { // first frame of a level: land on target, no pan cam.x = tx; cam.y = ty; cam.zoom = tz; cam.snap = false; return; } cam.x += (tx - cam.x) * 0.06; cam.y += (ty - cam.y) * 0.06; cam.zoom = (cam.zoom || 1) + (tz - (cam.zoom || 1)) * 0.08; } P.decayCamera = function(g, dt) { if (g.camera.shake > 0) { g.camera.shake *= Math.pow(0.03, dt); // fast decay if (g.camera.shake < 0.3) g.camera.shake = 0; } } }; });