@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
75 lines (59 loc) • 2.44 kB
JavaScript
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;
}