对于第一个球,代码原本是能够正常工作的,但是当执行到这一句:
for Ball in balls:
时,你在局部作用域中引入了一个名为Ball
的变量,这覆盖了全局作用域中的Ball
类。为了修复这个问题,我们可以将循环内的变量名改为ball
,这样就不会与全局类名冲突,然后对ball
对象调用.draw()
方法。
如果你坚持要在局部作用域中使用Ball
作为变量名,还有一种解决方案,就是在函数定义时将Ball
类作为默认参数传递进来:
def run(cls=Ball):
然而,在您提供的修改后的代码中,Ball
类的定义保持不变,但您已将balls
列表移动到了Ball
类内部,这是不合理的,因为balls
应该是存储所有Ball
实例的一个全局列表,不应该作为单个Ball
对象的属性。
同时,Ball
类的draw
方法现在接收width
和height
参数,并且在方法内部重新调用了pygame.display.set_mode()
,这通常是不必要的,因为只需要在初始化窗口时调用一次。
以下是针对上述问题优化过的代码版本:
import pygame
import math
pygame.init()
# 屏幕设置...
framespd = 30
gravity = 1
t = 0.01
clock = pygame.time.Clock()
width, height = 1000, 1000
pygame.display.set_caption("Orbit Take 1")
screen = pygame.display.set_mode((width, height))
class Ball:
def __init__(self, angle, velocity, radius, color, x_pos, y_pos):
self.angle = angle
self.velocity = velocity
self.radius = radius
self.color = color
self.x_pos = x_pos
self.y_pos = y_pos
def draw(self):
pygame.draw.circle(screen, self.color, (self.x_pos, self.y_pos), self.radius)
def true_velocity_x(self):
true_velocity_x = self.velocity * math.cos(self.angle)
def true_velocity_y(self):
true_velocity_y = self.velocity * math.sin(self.angle)
new_velocity_y = true_velocity_y + (gravity * t)
balls = []
def run():
running = True
while running:
clock.tick(framespd)
# 获取用户输入要创建的球数量
number_balls = int(input("请输入球的数量: "))
while len(balls) < number_balls:
# 获取球的属性值
a = input("角度: ")
v = input("速度: ")
r = input("半径: ")
c = input("颜色: ")
x_pos = '0'
y_pos = '500'
balls.append(Ball(a, v, r, c, x_pos, y_pos))
screen.fill('black')
# 绘制所有球体
# 使用不同的变量名避免覆盖全局类名
for ball_instance in balls:
ball_instance.draw()
# 更新位置(这部分未完成)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()
pygame.quit()
run()