fuzzyworld

herd / commit

Add immutable Vec2 math utility

5edd30c70c621485064636c5da45e080ac54f662 · Pavel Safronov · 2026-05-16 22:03:18 -0700 · parents 399ccff39f39

Add immutable Vec2 math utility

Covers add, sub, scale, normalize, limit, lerp, distance, and lengthSq.
Uses explicit field declarations to satisfy TypeScript erasableSyntaxOnly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
 src/math/Vec2.ts | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/src/math/Vec2.ts b/src/math/Vec2.ts
new file mode 100644
index 0000000..1372605
--- /dev/null
+++ b/src/math/Vec2.ts
@@ -0,0 +1,31 @@
+export class Vec2 {
+  readonly x: number
+  readonly y: number
+  constructor(x: number, y: number) { this.x = x; this.y = y }
+
+  add(v: Vec2): Vec2 { return new Vec2(this.x + v.x, this.y + v.y) }
+  sub(v: Vec2): Vec2 { return new Vec2(this.x - v.x, this.y - v.y) }
+  scale(s: number): Vec2 { return new Vec2(this.x * s, this.y * s) }
+
+  length(): number { return Math.sqrt(this.x * this.x + this.y * this.y) }
+  lengthSq(): number { return this.x * this.x + this.y * this.y }
+
+  normalize(): Vec2 {
+    const len = this.length()
+    return len > 0 ? this.scale(1 / len) : Vec2.ZERO
+  }
+
+  limit(max: number): Vec2 {
+    const len = this.length()
+    return len > max ? this.scale(max / len) : this
+  }
+
+  lerp(v: Vec2, t: number): Vec2 {
+    return new Vec2(this.x + (v.x - this.x) * t, this.y + (v.y - this.y) * t)
+  }
+
+  distanceTo(v: Vec2): number { return this.sub(v).length() }
+  distanceSqTo(v: Vec2): number { return this.sub(v).lengthSq() }
+
+  static readonly ZERO = new Vec2(0, 0)
+}