import { Point } from "./common"; function trueMod(v: number, max: number): number { return ((v % max) + max) % max; } export default class Vec2d implements Point { x: number; y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } static random(maxX: number, maxY: number) { return new Vec2d(Math.random() * maxX, Math.random() * maxY); } toString() { return `[${this.x}, ${this.y}]`; } normalize(): Vec2d { const len = this.length(); return new Vec2d(this.x / len, this.y / len); } scale(scalar: number): Vec2d { return new Vec2d(this.x * scalar, this.y * scalar); } add(other: Vec2d): Vec2d { return new Vec2d(this.x + other.x, this.y + other.y); } sub(other: Vec2d): Vec2d { return new Vec2d(this.x - other.x, this.y - other.y); } length(): number { return Math.sqrt(this.x * this.x + this.y * this.y); } distance(other: Vec2d): number { return this.sub(other).length(); } lerp(other: Vec2d, t: number): Vec2d { // (1-t)*A + B*t return this.scale(1 - t).add(other.scale(t)); } clamp(min: Vec2d, max: Vec2d): Vec2d { return new Vec2d( Math.min(Math.max(this.x, min.x), max.x), Math.min(Math.max(this.y, min.y), max.y) ); } wrap(bounds: Vec2d) { return new Vec2d(trueMod(this.x, bounds.x), trueMod(this.y, bounds.y)); } }