---@class Vector2 local Vector2 = {} Vector2.__index = Vector2 function Vector2.new(x, y) return setmetatable({ x = x or 0, y = y or 0 }, Vector2) end function Vector2:copy() return Vector2.new(self.x, self.y) end function Vector2:__tostring() return string.format("Vector2(%.3f, %.3f)", self.x, self.y) end function Vector2:add(v) return Vector2.new(self.x + v.x, self.y + v.y) end function Vector2:sub(v) return Vector2.new(self.x - v.x, self.y - v.y) end function Vector2:mul(scalar) return Vector2.new(self.x * scalar, self.y * scalar) end function Vector2:div(scalar) return Vector2.new(self.x / scalar, self.y / scalar) end function Vector2.__add(self, v) return Vector2.new(self.x + v.x, self.y + v.y) end function Vector2.__sub(self, v) return Vector2.new(self.x - v.x, self.y - v.y) end function Vector2:length() return math.sqrt(self.x^2 + self.y^2) end function Vector2:lengthSq() return self.x^2 + self.y^2 end function Vector2:addX(dx) self.x = self.x + dx return self end function Vector2:addY(dy) self.y = self.y + dy return self end function Vector2:normalize() local len = self:length() if len == 0 then return Vector2.new(0, 0) end return Vector2.new(self.x / len, self.y / len) end function Vector2:dot(v) return self.x * v.x + self.y * v.y end function Vector2:distanceTo(v) return (self:sub(v)):length() end function Vector2:distanceToSq(v) return (self:sub(v)):lengthSq() end function Vector2:equals(v, epsilon) epsilon = epsilon or 1e-5 return math.abs(self.x - v.x) < epsilon and math.abs(self.y - v.y) < epsilon end function Vector2:map(func) return Vector2.new(func(self.x), func(self.y)) end function Vector2:toTable() return { x = self.x, y = self.y } end function Vector2.fromTable(tbl) return Vector2.new(tbl.x, tbl.y) end function Vector2.fromArray(tbl) return Vector2.new(tbl[1], tbl[2]) end function Vector2:toArray() return {self.x, self.y} end function Vector2:unpack() return self.x, self.y end return Vector2