export class Vector { constructor(x = 0, y = 0) { this.x = x; this.y = y; } add(vector) { this.x += vector.x; this.y += vector.y; return this; } addMul(vector, scalar) { this.x += vector.x * scalar; this.y += vector.y * scalar; return this; } sub(vector) { this.x -= vector.x; this.y -= vector.y; return this; } mul(scalar) { this.x *= scalar; this.y *= scalar; return this; } div(scalar) { return this.mul(1 / scalar); } rotate(angle) { const cos = Math.cos(angle); const sin = Math.sin(angle); const nextX = cos * this.x - sin * this.y; const nextY = cos * this.y + sin * this.x; this.x = nextX; this.y = nextY; return this; } angle() { return Math.PI / 2 - Math.atan2(this.x, this.y); } normSquared() { return this.x * this.x + this.y * this.y; } static distSquared(lhs, rhs) { return ( (lhs.x - rhs.x) * (lhs.x - rhs.x) + (lhs.y - rhs.y) * (lhs.y - rhs.y) ); } reset() { this.x = 0; this.y = 0; return this; } clone() { return new Vector(this.x, this.y); } } export class Rectangle { constructor(x, y, w, h) { this.x = x; this.y = y; this.w = w; this.h = h; this.center = new Vector(x + w / 2, y + h / 2); } distance(point) { return Math.hypot( Math.max(point.x - this.x - this.w, 0, this.x - point.x), Math.max(point.y - this.y - this.h, 0, this.y - point.y), ); } draw(ctx) { ctx.rect(this.x, this.y, this.w, this.h); } } export class Circle { constructor(x, y, r) { this.r = r; this.center = new Vector(x, y); } distance(point) { return Math.hypot( this.center.x - point.x, this.center.y - point.y, ) - this.r; } draw(ctx) { ctx.moveTo(this.center.x + this.r, this.center.y); ctx.arc(this.center.x, this.center.y, this.r, 0, 2 * Math.PI, false); } }