import 'dart:math' as math; /// A lightweight, immutable 2D Vector/Coordinate system. class Coordinate2D implements Comparable { final double x; final double y; const Coordinate2D(this.x, this.y); /// Returns the angle in radians between this coordinate and [other]. /// Useful for "Look At" logic or determining steering direction. /// Result is between -pi and pi. double angleTo(Coordinate2D other) { return math.atan2(other.y - y, other.x - x); } /// Rotates the coordinate around (0,0) by [radians]. Coordinate2D rotate(double radians) { final cos = math.cos(radians); final sin = math.sin(radians); return Coordinate2D( (x * cos) - (y * sin), (x * sin) + (y * cos), ); } /// Linear Interpolation: Slides between this and [target] by [t] (0.0 to 1.0). /// Perfect for smooth camera follows or "lerping" an object to a new spot. Coordinate2D lerp(Coordinate2D target, double t) { return Coordinate2D( x + (target.x - x) * t, y + (target.y - y) * t, ); } double get magnitude => math.sqrt(x * x + y * y); Coordinate2D get normalized { final m = magnitude; if (m == 0) return const Coordinate2D(0, 0); return Coordinate2D(x / m, y / m); } double dot(Coordinate2D other) => (x * other.x) + (y * other.y); double distanceTo(Coordinate2D other) => (this - other).magnitude; Coordinate2D operator +(Coordinate2D other) => Coordinate2D(x + other.x, y + other.y); Coordinate2D operator -(Coordinate2D other) => Coordinate2D(x - other.x, y - other.y); Coordinate2D operator *(double n) => Coordinate2D(x * n, y * n); Coordinate2D operator /(double n) => Coordinate2D(x / n, y / n); @override bool operator ==(Object other) => identical(this, other) || other is Coordinate2D && x == other.x && y == other.y; @override int get hashCode => Object.hash(x, y); @override int compareTo(Coordinate2D other) => x != other.x ? x.compareTo(other.x) : y.compareTo(other.y); @override String toString() => 'Coordinate2D($x, $y)'; }