如何在Pygame中用三角学实现圆绕圆心旋转(不使用pygame.transform.rotate)
用三角学实现Pygame中圆及圆上点的旋转
我有一段简单的Pygame代码,可在窗口中绘制一个圆。我希望不使用
pygame.transform.rotate函数,而是通过三角学实现该圆绕其圆心旋转,同时让圆上的点p随之旋转。以下是我的代码:
import pygame from pygame.locals import QUIT class Circle: def __init__(self, x, y, radius): self.x = x self.y = y self.radius = radius def draw(self, window): pygame.draw.circle(window, BLACK, (self.x, self.y), self.radius) class Main: def __init__(self, width, height): self.WIDTH = width self.HEIGHT = height def components(self): self.win = pygame.display.set_mode((self.WIDTH, self.HEIGHT)) def Loop(self): self.run = True self.circle = Circle(100, 100, 50) while self.run: event = pygame.event.wait() if event.type == QUIT: self.run = False self.win.fill(WHITE) self.circle.draw(self.win) pygame.display.flip() WIDTH = 700 HEIGHT = 500 WHITE = (255, 255, 255) BLACK = (0, 0, 0) window = Main(WIDTH, HEIGHT) window.components() window.Loop()我的思路:假设有这样一个圆,我想通过三角学而不是内置函数,让圆上的点p随圆一起旋转。
实现思路
绕圆心旋转的核心是利用2D旋转的三角学公式:对于平面上的点$(x, y)$,绕原点逆时针旋转$\theta$弧度后的坐标为:
$$x' = x \cdot \cos\theta - y \cdot \sin\theta$$
$$y' = x \cdot \sin\theta + y \cdot \cos\theta$$
因为我们是绕圆的圆心旋转(而非坐标原点),所以需要三步:
- 将圆上点的坐标转换为以圆心为原点的局部坐标系(减去圆心坐标)
- 对局部坐标应用旋转公式
- 将旋转后的局部坐标转换回全局坐标系(加上圆心坐标)
修改后的完整代码
import pygame from pygame.locals import QUIT import math class Circle: def __init__(self, x, y, radius): self.x = x self.y = y self.radius = radius # 初始化圆上点P的初始角度(初始在圆的右侧) self.p_angle = 0 # 旋转速度(弧度/帧) self.rotate_speed = 0.02 def update(self): # 更新点P的旋转角度 self.p_angle += self.rotate_speed # 确保角度在0-2π范围内循环,避免数值溢出 if self.p_angle > 2 * math.pi: self.p_angle -= 2 * math.pi def get_p_position(self): # 计算点P在局部坐标系的位置(基于当前角度) local_x = self.radius * math.cos(self.p_angle) local_y = self.radius * math.sin(self.p_angle) # 转换为全局坐标 return (self.x + local_x, self.y + local_y) def draw(self, window): # 绘制圆 pygame.draw.circle(window, BLACK, (self.x, self.y), self.radius) # 获取点P的位置并绘制(转为整数适配像素坐标) p_pos = self.get_p_position() pygame.draw.circle(window, (255, 0, 0), (int(p_pos[0]), int(p_pos[1])), 5) class Main: def __init__(self, width, height): self.WIDTH = width self.HEIGHT = height def components(self): self.win = pygame.display.set_mode((self.WIDTH, self.HEIGHT)) pygame.display.set_caption("旋转的圆与点") def Loop(self): self.run = True self.circle = Circle(100, 100, 50) # 用Clock控制帧率,保证旋转速度稳定 clock = pygame.time.Clock() while self.run: # 处理所有事件,避免窗口阻塞 for event in pygame.event.get(): if event.type == QUIT: self.run = False # 更新旋转状态 self.circle.update() self.win.fill(WHITE) self.circle.draw(self.win) pygame.display.flip() # 固定帧率为60帧/秒 clock.tick(60) WIDTH = 700 HEIGHT = 500 WHITE = (255, 255, 255) BLACK = (0, 0, 0) window = Main(WIDTH, HEIGHT) window.components() window.Loop() pygame.quit()
关键代码解释
- 角度更新逻辑:
update方法中每帧增加固定弧度值,同时限制角度范围在0到2π之间,保证循环旋转。 - 点P坐标计算:通过三角函数直接计算点P在圆上的实时位置,无需依赖Pygame的旋转函数,完全基于三角学实现。
- 帧率控制:使用
pygame.time.Clock()固定帧率,避免不同设备上旋转速度差异过大。 - 事件处理优化:替换
event.wait()为pygame.event.get(),解决窗口无法及时响应关闭操作的问题。
内容的提问来源于stack exchange,提问作者user19909333
相关产品推荐
相关产品推荐

