You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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$$

因为我们是绕圆的圆心旋转(而非坐标原点),所以需要三步:

  1. 将圆上点的坐标转换为以圆心为原点的局部坐标系(减去圆心坐标)
  2. 对局部坐标应用旋转公式
  3. 将旋转后的局部坐标转换回全局坐标系(加上圆心坐标)

修改后的完整代码

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()

关键代码解释

  1. 角度更新逻辑:update方法中每帧增加固定弧度值,同时限制角度范围在0到2π之间,保证循环旋转。
  2. 点P坐标计算:通过三角函数直接计算点P在圆上的实时位置,无需依赖Pygame的旋转函数,完全基于三角学实现。
  3. 帧率控制:使用pygame.time.Clock()固定帧率,避免不同设备上旋转速度差异过大。
  4. 事件处理优化:替换event.wait()为pygame.event.get(),解决窗口无法及时响应关闭操作的问题。

内容的提问来源于stack exchange,提问作者user19909333

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:49:14