import pygame import math class Vector2D: def __init__(self, x: float = 0, y: float = 0): self._vector = pygame.Vector2(x, y) @property def x(self) -> float: return self._vector.x @x.setter def x(self, value: float): self._vector.x = value @property def y(self) -> float: return self._vector.y @y.setter def y(self, value: float): self._vector.y = value def __add__(self, other): if isinstance(other, Vector2D): return Vector2D(self.x + other.x, self.y + other.y) else: result = self._vector + other._vector return Vector2D(result.x, result.y) def __sub__(self, other): if isinstance(other, Vector2D): return Vector2D(self.x - other.x, self.y - other.y) else: result = self._vector - other._vector return Vector2D(result.x, result.y) def __mul__(self, scalar): if isinstance(scalar, Vector2D): return Vector2D(self.x * scalar.x, self.y * scalar.y) else: result = self._vector * scalar return Vector2D(result.x, result.y) def __truediv__(self, other): if isinstance(other, Vector2D): return Vector2D(self.x / other.x, self.y / other.y) else: result = self._vector / other return Vector2D(result.x, result.y) def length(self): return self._vector.length() def normalize(self): result = self._vector.normalize() return Vector2D(result.x, result.y) def dot(self, other): if isinstance(other, Vector2D): return self._vector.dot(other._vector) else: return self._vector.dot(other) class Transform2D: IDENTITY = None FLIP_X = None FLIP_Y = None def __init__(self, position: Vector2D = None, rotation: float = 0.0, scale: Vector2D = None): """ 初始化变换矩阵 Args: position: 位置向量 rotation: 旋转角度(弧度) scale: 缩放向量 """ if position is None: position = Vector2D(0, 0) if scale is None: scale = Vector2D(1.0, 1.0) self._set_transform(position, rotation, scale) def _set_transform(self, position: Vector2D, rotation: float, scale: Vector2D): """ 根据位置、旋转和缩放设置变换矩阵 """ cos = math.cos(rotation) sin = math.sin(rotation) # 设置基向量(旋转和缩放的组合) self.x = Vector2D(cos * scale.x, sin * scale.x) self.y = Vector2D(-sin * scale.y, cos * scale.y) # 设置原点(平移) self.origin = position @property def position(self) -> Vector2D: """获取位置""" return self.origin @position.setter def position(self, value: Vector2D): """设置位置""" self.origin = value @property def scale(self) -> Vector2D: """获取缩放""" # 计算基向量的长度来得到缩放因子 scale_x = math.sqrt(self.x.x * self.x.x + self.x.y * self.x.y) scale_y = math.sqrt(self.y.x * self.y.x + self.y.y * self.y.y) return Vector2D(scale_x, scale_y) @scale.setter def scale(self, value: Vector2D): """设置缩放""" current_scale = self.scale if current_scale.x != 0 and current_scale.y != 0: # 调整基向量以适应新的缩放 scale_ratio_x = value.x / current_scale.x scale_ratio_y = value.y / current_scale.y self.x = Vector2D(self.x.x * scale_ratio_x, self.x.y * scale_ratio_x) self.y = Vector2D(self.y.x * scale_ratio_y, self.y.y * scale_ratio_y) @property def rotation(self) -> float: """获取旋转角度""" return math.atan2(self.x.y, self.x.x) @rotation.setter def rotation(self, value: float): """设置旋转角度""" current_scale = self.scale cos = math.cos(value) sin = math.sin(value) self.x = Vector2D(cos * current_scale.x, sin * current_scale.x) self.y = Vector2D(-sin * current_scale.y, cos * current_scale.y) def transform_point(self, point: Vector2D) -> Vector2D: """ 应用变换到点 Args: point: 要变换的点 Returns: 变换后的点 """ # 应用线性变换然后加上平移 x = self.x * point.x y = self.y * point.y return self.origin + x + y def multiply(self, other: 'Transform2D') -> 'Transform2D': """ 将另一个变换应用到当前变换 Args: other: 要应用的变换 Returns: 新的变换对象 """ # 组合两个变换矩阵 new_x = Vector2D( self.x.x * other.x.x + self.y.x * other.x.y, self.x.y * other.x.x + self.y.y * other.x.y ) new_y = Vector2D( self.x.x * other.y.x + self.y.x * other.y.y, self.x.y * other.y.x + self.y.y * other.y.y ) new_origin = self.transform_point(other.origin) result = Transform2D() result.x = new_x result.y = new_y result.origin = new_origin return result def inverse(self) -> 'Transform2D': """ 计算逆变换 Returns: 逆变换 """ # 计算2x2矩阵的行列式 det = self.x.x * self.y.y - self.x.y * self.y.x if abs(det) < 1e-10: raise ValueError("Transform is not invertible") inv_det = 1.0 / det # 计算逆矩阵的基向量 inv_x = Vector2D( self.y.y * inv_det, -self.x.y * inv_det ) inv_y = Vector2D( -self.y.x * inv_det, self.x.x * inv_det ) # 计算逆矩阵的原点 origin_dot = self.origin.x * inv_x.x + self.origin.y * inv_x.y origin_dot2 = self.origin.x * inv_y.x + self.origin.y * inv_y.y inv_origin = Vector2D(-origin_dot, -origin_dot2) result = Transform2D() result.x = inv_x result.y = inv_y result.origin = inv_origin return result # 初始化预定义常量 Transform2D.IDENTITY = Transform2D() Transform2D.FLIP_X = Transform2D(scale=Vector2D(-1, 1)) Transform2D.FLIP_Y = Transform2D(scale=Vector2D(1, -1))