import Angle from './Angle' import RandomGenerator from './RandomGenerator' export type Tuple = [number, number] export default class Vector2 { public static random(rng: RandomGenerator, min: number, max: number) { return new Vector2([rng.uniformFloat(min, max), rng.uniformFloat(min, max)]) } public static randomInt(rng: RandomGenerator, min: number, max: number) { return new Vector2([rng.uniformInt(min, max), rng.uniformInt(min, max)]) } constructor(public components: Tuple) {} public get x() { return this.components[0] } public get y() { return this.components[1] } public set x(value: number) { this.components[0] = value } public set y(value: number) { this.components[1] = value } public get magnitude(): number { return Math.sqrt(this.x ** 2 + this.y ** 2) } public get normal(): Vector2 { const mag = this.magnitude return new Vector2([this.x / mag, this.y / mag]) } public get angle(): Angle { return new Angle(Math.atan2(this.y, this.x), 'rad') } public dot(other: Vector2) { return this.x * other.x + this.y * other.y } public add(other: Vector2) { return new Vector2([this.x + other.x, this.y + other.y]) } public subtract(other: Vector2) { return new Vector2([this.x - other.x, this.y - other.y]) } public subtractScalar(scalar: number) { return new Vector2([this.x - scalar, this.y - scalar]) } public divideScalar(scalar: number) { return new Vector2([this.x / scalar, this.y / scalar]) } public divide(other: Vector2) { return new Vector2([this.x / other.x, this.y / other.y]) } public scale(scalar: number) { return new Vector2([this.x * scalar, this.y * scalar]) } public lerp(other: Vector2, alpha: number): Vector2 { return this.add(other.subtract(this).scale(alpha)) } public rotate(angle: number): Vector2 { const cos = Math.cos(angle) const sin = Math.sin(angle) return new Vector2([ this.x * cos - this.y * sin, this.x * sin + this.y * cos ]) } public clamp(min: number, max: number): Vector2 { return new Vector2([ Math.min(Math.max(this.x, min), max), Math.min(Math.max(this.y, min), max) ]) } /** * Computes the Euclidean distance to an other vector */ public euclideanDistance(other: this): number { return Math.sqrt(this.euclideanDistanceSqr(other)) } /** * Computes the Euclidean distance to an other vector */ public euclideanDistanceSqr(other: this): number { return (this.x - other.x) ** 2 + (this.y - other.y) ** 2 } }