UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

75 lines (59 loc) 2.44 kB
import { v3_dot } from "../../core/geom/vec3/v3_dot.js"; import { solveQuadratic } from "../../core/math/solveQuadratic.js"; /** * * @type {number[]} */ const q_roots = []; /** * Given position of the source point, and target moving at a constant velocity, compute intercept. * Simple example would be {@link target} being enemy running, and {@link source} being position of our archer, given that the arrow speed is {@link sourceSpeed}, where should the archer aim at in order to hit the moving target? * @param {Vector3} result This is where the intercept point will be written if solution is found * @param {Vector3} source Where to launch a projectile from * @param {Vector3} target Where the target currently is * @param {Vector3} targetVelocity Target's current velocity vector * @param {number} sourceSpeed Speed of the projectile in question * @return {boolean} true iff there is at least one real solution */ export function computeInterceptPoint( result, source, target, targetVelocity, sourceSpeed ) { if (sourceSpeed < 0) { // negative speed is invalid return false; } const d_ts_x = target.x - source.x; const d_ts_y = target.y - source.y; const d_ts_z = target.z - source.z; // Get quadratic equation components const a = targetVelocity.dot(targetVelocity) - sourceSpeed * sourceSpeed; const b = 2 * v3_dot(targetVelocity.x, targetVelocity.y, targetVelocity.z, d_ts_x, d_ts_y, d_ts_z); const c = v3_dot( d_ts_x, d_ts_y, d_ts_z, d_ts_x, d_ts_y, d_ts_z ); // Solve quadratic const root_count = solveQuadratic(q_roots, 0, a, b, c); // See quad(), below // Find smallest positive solution if (root_count > 0) { const root_0 = q_roots[0]; const root_1 = q_roots[1]; let t = Math.min(root_0, root_1); if (t < 0) { // one of the roots is negative, which would produce imaginary solution, so let's try to pick the other one t = Math.max(root_0, root_1); } if (t >= 0) { result.copy(targetVelocity); result.multiplyScalar(t); result.add(target); return true; } // if we got to this point, that means that both roots are imaginary, so there is no real solution } return false; }