撒科打诨
回答问题1:是的。肯定有很多更有效的方法来做事。没有必要为方向制造那么多变数。简单地说direction = [True, False],其中direction[0]代表not direction[0]x 轴的左,代表右。同样,direction[1]代表 y 轴。这也解决了您在开始时随机化方向的问题。您只需 direction = [random.randint(0, 1), random.randint(0, 1)]在 init 方法中执行即可随机化方向。同样的方式,也列出速度清单。self.speed = [0.5, random.uniform(0.1, 1)]。这样,左右方向的速度将始终相同,但 y 将根据所选的随机数而变化,因此存在适当的随机性,并且您也不必硬编码随机方向。这样,移动变得非常简单。class Ball:def __init__(self, x, y, color, size): self.x = x self.y = y self.color = color self.size = size self.direction = [random.randint(0, 1), random.randint(0, 1)] self.speed = [0.5, random.uniform(0.1, 1)] def draw(self, display): pygame.draw.rect(display, self.color, (self.x, self.y, self.size, self.size))def move(self): if self.direction[0]: self.x += self.speed[0] else: self.x -= self.speed[0] if self.direction[1]: self.y += self.speed[0] else: self.y -= self.speed[0]因为我们定义的方向方向是布尔值,所以改变状态也变得非常容易。如果球击中球拍,您可以简单地切换direction[0] = not direction[0]x 中的布尔值并为 y 选择一个新的随机数,而不是手动分配布尔值。def switchDirection(self): self.direction = not self.direction self.speed[1] = random.uniform(0.1, 1)move通过为 Paddle 类提供一个函数而不是在主循环中移动,Paddle 也可以稍微改进。这只是意味着您必须编写更少的代码。def move(self, vel, up=pygame.K_UP, down=pygame.K_DOWN): keys = pygame.key.get_perssed() if keys[up]: self.y -= vel if keys[down]: self.y += vel对于碰撞,我建议使用pygame.Rect()andcolliderect因为它更强大并且可能也更有效。例子:import randomimport pygameWIN = pygame.displayD = WIN.set_mode((800, 500))class Paddle: def __init__(self, x, y, width, height, vel, color): self.x = x self.y = y self.width = width self.height = height self.vel = vel self.color = color def move(self, vel, up=pygame.K_UP, down=pygame.K_DOWN): keys = pygame.key.get_pressed() if keys[up]: self.y -= vel if keys[down]: self.y += vel def draw(self, window): pygame.draw.rect(window, self.color, (self.x, self.y, self.width, self.height), 0) def getRect(self): return pygame.Rect(self.x, self.y, self.width, self.height)left_paddle = Paddle(20, 100, 10, 50, 5, (0, 0, 0))right_paddle = Paddle(770, 350, 10, 50, 5, (0, 0, 0))class Ball: def __init__(self, x, y, color, size): self.x = x self.y = y self.color = color self.size = size self.direction = [random.randint(0, 1), random.randint(0, 1)] self.speed = [0.3, random.uniform(0.2, 0.2)] def draw(self, window): pygame.draw.rect(window, self.color, (self.x, self.y, self.size, self.size)) def switchDirection(self): self.direction[0] = not self.direction[0] self.direction[1] = not self.direction[1] self.speed = [0.2, random.uniform(0.1, 0.5)] def bounce(self): self.direction[1] = not self.direction[1] self.speed = [0.2, random.uniform(0.01, 0.2)] def move(self): if self.direction[0]: self.x += self.speed[0] else: self.x -= self.speed[0] if self.direction[1]: self.y += self.speed[1] else: self.y -= self.speed[1] def getRect(self): return pygame.Rect(self.x, self.y, self.size, self.size) def boundaries(self): if ball.x <= 10: self.switchDirection() if ball.x + self.size >= 800: self.switchDirection() if ball.y + self.size >= 490: self.bounce() if ball.y <= 0: self.bounce()ball = Ball(400, 250, (255, 0, 0), 20)while True: pygame.event.get() D.fill((255, 255, 255)) ball.draw(D) ball.boundaries() ball.move() #print(ball.x, ball.y) left_paddle.draw(D) right_paddle.draw(D) right_paddle.move(0.4) left_paddle.move(0.4, down=pygame.K_s, up=pygame.K_w) if left_paddle.getRect().colliderect(ball.getRect()): ball.switchDirection() if right_paddle.getRect().colliderect(ball.getRect()): ball.switchDirection() WIN.flip()
SMILET
关于如何减少所有球运动/碰撞代码并提高可重用性的一些值得思考的地方:import pygameclass Ball: def __init__(self, bounds, color): from random import randint, choice self.bounds = bounds self.position = pygame.math.Vector2( randint(self.bounds.left, self.bounds.left+self.bounds.width), randint(self.bounds.top, self.bounds.top+self.bounds.height) ) self.velocity = pygame.math.Vector2(choice((-1, 1)), choice((-1, 1))) self.color = color self.size = 8 def draw(self, window): pygame.draw.rect( window, self.color, ( self.position.x-self.size, self.position.y-self.size, self.size*2, self.size*2 ), 0 ) def update(self): self.position.x += self.velocity.x self.position.y += self.velocity.y if not self.bounds.left+self.size < self.position.x < self.bounds.left+self.bounds.width-self.size: self.velocity.x *= -1 if not self.bounds.top+self.size < self.position.y < self.bounds.top+self.bounds.height-self.size: self.velocity.y *= -1def main(): from random import randint window_width, window_height = 800, 500 window = pygame.display.set_mode((window_width, window_height)) pygame.display.set_caption("Pong") clock = pygame.time.Clock() black = (0, 0, 0) white = (255, 255, 255) padding = 20 bounds = pygame.Rect(padding, padding, window_width-(padding*2), window_height-(padding*2)) ball = Ball(bounds, white) def redraw_window(): window.fill(black) pygame.draw.rect( window, white, ( padding, padding, window_width-(padding*2), window_height-(padding*2) ), 1 ) ball.draw(window) pygame.display.update() while True: clock.tick(60) ball.update() for event in pygame.event.get(): if event.type == pygame.QUIT: break else: redraw_window() continue break pygame.quit() return 0 if __name__ == "__main__": import sys sys.exit(main())这不是一个完整的替代品,我只是重新实现了该类Ball。没有桨。本质上,在实例化一个球时,您传递一个pygame.Rect,它描述了允许球弹跳的边界。您还传递一个颜色元组。然后,球在边界内选择一个随机位置(该位置是 a pygame.math.Vector2,而不是存储x和y作为单独的实例变量)。球也有速度,它也是pygame.math.Vector2,因此您可以拥有独立的速度分量 - 一个用于x(水平速度),一个用于y(垂直速度)。球size的 简单地描述了球的尺寸。例如,如果size设置为8,则球将为 16x16 像素。该类Ball还有一个update方法,每个游戏循环迭代都会调用该方法。它将球移动到速度决定的下一个位置,并检查球是否与边界碰撞。如果是,则反转相应的速度分量。