/* ISLE SLINGERS -- physics/aim/index.js (submodule: aim) * 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: aimVector, trajectory. */ (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.aimVector = function(g, sling, drag) { var dx = sling.x - drag.x, dy = sling.y - drag.y; var len = Math.sqrt(dx * dx + dy * dy); if (len < P.MIN_PULL) return null; var cl = Math.min(len, P.MAX_PULL); var v = cl * P.LAUNCH_POWER; return { vx: (dx / len) * v, vy: (dy / len) * v, pull: cl }; } // Pure P.trajectory preview: identical integrator + substepping as the live // sim (2x 1/120 per output point), so the dotted preview matches the real // flight exactly. Gravity + drag only; stops at the ground. P.trajectory = function(g, sx, sy, vx, vy, steps) { var pts = []; var x = sx, y = sy, i, sub; for (i = 0; i < steps; i++) { for (sub = 0; sub < 2; sub++) { var dt = 1 / 120; var nvy = vy + P.GRAVITY * dt; x += vx * dt; y += (vy + nvy) * 0.5 * dt; vx *= P.AIR_DRAG; vy = nvy; } if (y > P.WORLD.ground - 18) { pts.push({ x: x, y: P.WORLD.ground - 18, last: true }); break; } pts.push({ x: x, y: y, last: false }); } return pts; } }; });