Pygame轨道模拟器中pygame.draw.circle的center参数报错问题
行星轨道模拟器Pygame报错排查
问题描述
基于Pygame开发的行星轨道模拟器运行时界面黑屏,同时抛出TypeError: center argument must be a pair of numbers错误。已将行星与太阳的坐标转换为整数作为绘制圆心,但仍无法正常显示。
完整代码
import pygame import math # Set up the Pygame window pygame.init() WIDTH = 800 HEIGHT = 800 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Planet Orbit Simulator") # Define some constants G = 6.67430e-11 # gravitational constant TIMESTEP = 3600 # time step in seconds # Define the Planet and Sun classes class Planet: def __init__(self, x, y, mass, velocity): self.x = x self.y = y self.mass = mass self.velocity = velocity self.acceleration = (0, 0) def update(self): self.x += self.velocity[0] * TIMESTEP self.y += self.velocity[1] * TIMESTEP self.velocity = (self.velocity[0] + self.acceleration[0] * TIMESTEP, self.velocity[1] + self.acceleration[1] * TIMESTEP) class Sun: def __init__(self, x, y, mass): self.x = x self.y = y self.mass = mass # Define the main function def main(): # Set up the Sun and Planet sun = Sun(WIDTH//2, HEIGHT//2, 1.989e30) planet = Planet(WIDTH//2 + 147e9, HEIGHT//2, 5.972e24, (0, 30000)) # Set up the Pygame clock clock = pygame.time.Clock() # Start the main loop while True: # Handle events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() return # Calculate the gravitational force between the Sun and Planet distance = math.sqrt((planet.x - sun.x)**2 + (planet.y - sun.y)**2) force = G * sun.mass * planet.mass / distance**2 # Calculate the acceleration of the Planet acceleration = force / planet.mass acceleration_x = acceleration * (sun.x - planet.x) / distance acceleration_y = acceleration * (sun.y - planet.y) / distance planet.acceleration = (acceleration_x, acceleration_y) # Update the Planet planet.update() # Draw the Sun and Planet screen.fill((0, 0, 0)) sun_center = (int(sun.x), int(sun.y)) pygame.draw.circle(screen, (255, 255, 0), sun_center, 20) planet_center = (int(planet.x), int(planet.y)) pygame.draw.circle(screen, (255, 255, 255), planet_center, 5) # Update the Pygame display pygame.display.flip() # Limit the frame rate clock.tick(60) # Handle user input keys = pygame.key.get_pressed() if keys[pygame.K_UP]: planet.velocity = (planet.velocity[0], planet.velocity[1] - 1000) elif keys[pygame.K_DOWN]: planet.velocity = (planet.velocity[0], planet.velocity[1] + 1000) elif keys[pygame.K_RIGHT]: planet.velocity = (planet.velocity[0] + 1000, planet.velocity[1]) if __name__ == "__main__": main()
问题代码段
# Draw the Sun and Planet screen.fill((0, 0, 0)) sun_center = (int(sun.x), int(sun.y)) pygame.draw.circle(screen, (255, 255, 0), sun_center, 20) planet_center = (int(planet.x), int(planet.y)) pygame.draw.circle(screen, (255, 255, 255), planet_center, 5)
错误信息
pygame 2.0.1 (SDL 2.0.14, Python 3.9.13) Hello from the pygame community. https://www.pygame.org/contribute.html Traceback (most recent call last): File "C:/path/to/file.py", line 90, in <module> main() File "C:/path/to/file.py", line 70, in main pygame.draw.circle(screen, (255, 255, 255), planet_center, 5) TypeError: center argument must be a pair of numbers
问题原因
核心问题是天文单位与屏幕像素单位未做转换:行星的初始真实坐标(WIDTH//2 +147e9)是一个极大数值,远超出屏幕800x800的范围。尽管代码中转换为整数,但超大数值在Pygame底层处理时会触发异常,抛出center argument must be a pair of numbers错误;同时行星位置完全超出屏幕可视区域,这也是界面黑屏的原因。
解决方法
添加缩放因子,将真实天文坐标转换为屏幕像素范围内的坐标,推荐采用“物理计算用真实值,绘制时转换坐标”的方案,既保证物理模拟准确性,又解决显示问题:
- 在常量定义部分添加缩放因子(可根据显示效果调整):
SCALE = 2e-9 # 示例:1米对应2e-9像素,147e9米对应294像素,适配800x800屏幕
- 修改绘制部分的代码,将行星的真实相对坐标缩放后叠加到太阳的屏幕坐标上:
# Draw the Sun and Planet screen.fill((0, 0, 0)) sun_center = (int(sun.x), int(sun.y)) pygame.draw.circle(screen, (255, 255, 0), sun_center, 20) # 计算行星在屏幕上的坐标:太阳屏幕坐标 + 行星相对太阳的真实偏移 * 缩放因子 planet_screen_x = int(sun.x + (planet.x - sun.x) * SCALE) planet_screen_y = int(sun.y + (planet.y - sun.y) * SCALE) planet_center = (planet_screen_x, planet_screen_y) pygame.draw.circle(screen, (255, 255, 255), planet_center, 5)
- (可选)若觉得轨道运动速度过快/过慢,可调整
TIMESTEP数值,比如改为TIMESTEP = 3600*24(模拟一天的时间步长)。
内容的提问来源于stack exchange,提问作者Tom Williams
相关产品推荐
相关产品推荐

