UNPKG

gibbon.js

Version:

Actor/Component system for use with pixi.js.

237 lines (176 loc) 4.95 kB
import { Matrix, Polygon } from 'pixi.js'; import { TPoint } from '../data/geom'; export const PI_2 = 2 * Math.PI; export const clampTo2Pi = (v: number) => { return (v > PI_2 || v < -PI_2) ? v %= PI_2 : v; } /** * Clamp angle to [-Math.PI, Math.PI] */ export const clampToPi = (a: number) => { a = a % PI_2; if (a > Math.PI) { a -= PI_2; } else if (a < -Math.PI) { a += PI_2; } return a; } export const getLength = (p: TPoint) => { return Math.sqrt(p.x * p.x + p.y * p.y); } /** * Returns the distance between two points. */ export const dist = (p1: TPoint, p2: TPoint) => { const dx = p2.x - p1.x, dy = p2.y - p1.y; return Math.sqrt(dx * dx + dy * dy); } /** * Get a point located by travelling along a sequence of points * for the given distance. * @param points * @param dist * @returns {Point} */ export const getTravelPt = (points: TPoint[], dist: number) => { const count = points.length; let curPt, prevPt = points[0]; let curDist = 0; let d; for (let i = 1; i < count; i++) { curPt = points[i]; const dx = curPt.x - prevPt.x; const dy = curPt.y - prevPt.y; d = Math.sqrt(dx * dx + dy * dy); if ((curDist + d) >= dist) { // distance pt comes before curPt. d = (dist - curDist) / d; // percent between points. // TODO: check if curPt is right here. return { x: curPt.x + d * dx, y: curPt.y + d * dy }; } curDist += d; prevPt = curPt; } //for-loop. // point not found. return { x: prevPt.x, y: prevPt.y }; } /** * Return interpolated point. * @param p0 * @param p1 * @param {number} t */ export const lerpPt = (p0: TPoint, p1: TPoint, t: number) => { return { x: (1 - t) * p0.x + t * p1.x, y: (1 - t) * p0.y + t * p1.y }; } /** * Set p0 to the linear interpolation of p0 and p1. * @param p0 * @param p1 * @param {number} t * @returns {Point} returns p0. */ export const setLerp = (p0: TPoint, p1: TPoint, t: number) => { p0.x = (1 - t) * p0.x + t * p1.x; p0.y = (1 - t) * p0.y + t * p1.y; } /** * Return a point falling a given distance between two points. * @param p1 * @param p2 * @param {number} dist - distance along the path from p1 to p2 * to get the point of. Actual distance, not a percent. */ export const getMidPt = (p1: TPoint, p2: TPoint, dist: number) => { const dx = p2.x - p1.x; const dy = p2.y - p1.y; let d = Math.sqrt(dx * dx + dy * dy); if (d === 0) return { x: 0, y: 0 }; d = dist / d; // convert from distance to percent. return { x: p1.x + dx * d, y: p1.y + dy * d }; } /** * Get the center of an array of points. * @returns {Point} Center point of all points. */ export const getCenter = (points: TPoint[]) => { const len = points.length; if (len === 0) return { x: 0, y: 0 }; let p = points[0]; let x = p.x, y = p.y; for (let i = len - 1; i >= 1; i--) { p = points[i]; x += p.x; y += p.y; } return { x: x / len, y: y / len }; } /** * sets the values of mat to a reflection across normal axis a,b * without altering tx,ty. * @returns {Matrix} */ export const setReflect = (mat: Matrix, a: number, b: number) => { mat.set(1 - 2 * b * b, 2 * a * b, 2 * a * b, 1 - 2 * a * a, mat.tx, mat.ty); } /** * @returns reflection matrix across the normal a,b. */ export const reflection = (a: number, b: number) => { return new Matrix(1 - 2 * b * b, 2 * a * b, 2 * a * b, 1 - 2 * a * a); } /** * @returns returns vector orthogonal to p with length equal |p|. * Result is not normalized. */ export const othogonal = (p: TPoint) => { return { x: p.y, y: -p.x } } /** * @returns {number} - magnitude of the cross product p1xp2 * left hand rule; normals point screen upwards. */ export const cross = (p1: TPoint, p2: TPoint) => { return p1.x * p2.y - p1.y * p2.x; } /** * move() is separate from translate() because of how PIXI * handles Polygon point storage. * @param poly - polygon to translate. */ export const movePoly = (poly: Polygon, tx: number, ty: number) => { const points = poly.points; for (let i = points.length - 1; i >= 0; i--) { points[i] += ty; points[--i] += tx; } } /** * Translate an array of points by (tx,ty) * @property points */ export const translate = (points: TPoint[], tx: number, ty: number) => { for (let i = points.length - 1; i >= 0; i--) { const p = points[i]; p.x += tx; p.y += ty; } } /** * Rotate points about the origin. * @param points * @param theta - rotation in radians. * */ export const rotate = (points: TPoint[], theta: number) => { const cos = Math.cos(theta); const sin = Math.sin(theta); for (let i = points.length - 1; i >= 0; i--) { const p = points[i]; p.x = p.x * cos - p.y * sin; p.y = p.x * sin + p.y * cos; } }