如何仅在 pygame 中使用 "colliderect" 删除矩形 "hit" x 次
How to remove a rect in pygame using "colliderect" only if the rect has been "hit" x times
我正在制作一个 breakout 版本,虽然基础游戏可以运行,但我想制作关卡等。所以我想做的是在球击中 x 次之前,砖块不会被移除。
我试过添加一个计数器:
for brick in self.bricks:
if self.ball.colliderect(brick):
self.brick_counter += 1
self.score += 3
self.ball_vel[1] = -self.ball_vel[1]
if self.brick_counter == 2:
self.bricks.remove(brick)
break
但结果是球刚好穿过了砖块。
我也考虑过创建两层(或更多)砖块,但我不确定我将如何实现它。
完整代码如下:
import sys
import pygame
# Global variables is usually in the top of the document
SCREEN_SIZE = 750, 550
#OBJECT ATTRIBUTES
#PADDLE ATTRIBUTES
PADDLE_WIDTH = 54
PADDLE_HEIGHT = 10
MAX_PADDLE_X = SCREEN_SIZE[0] - PADDLE_WIDTH
PADDLE_Y = SCREEN_SIZE[1] - PADDLE_HEIGHT - 10
#BRICK ATTRIBUTES
BRICK_WIDTH = 75
BRICK_HEIGHT = 15
#BALL ATTRIBUTES
BALL_DIAMETER = 16
BALL_RADIUS = BALL_DIAMETER // 2
MAX_BALL_X = SCREEN_SIZE[0] - BALL_DIAMETER
MAX_BALL_Y = SCREEN_SIZE[1] - BALL_DIAMETER
#COLORS
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
CYAN = (0, 255, 255)
PINK = (255, 102, 255)
WHITE = (255, 255, 255)
NAVYBLUE = ( 60, 60, 100)
RED = (200, 0, 0)
DARKRED = (100, 0, 0)
ORANGE = (200, 100, 0)
DARKORANGE = (100, 50, 0)
YELLOW = (200, 200, 0)
DARKYELLOW = (100, 100, 0)
GREEN = ( 0, 200, 0)
DARKGREEN = ( 0, 100, 0)
BLUE = ( 0, 0, 200)
DARKBLUE = ( 0, 0, 100)
PURPLE = (200, 0, 200)
DARKPURPLE = (100, 0, 100)
RAINBOW = [(RED, DARKRED),(ORANGE,DARKORANGE),(YELLOW,DARKYELLOW),
(GREEN,DARKGREEN),(BLUE,DARKBLUE),(PURPLE,DARKPURPLE)]
BRICK_COLOR =(0, 255, 255)
# State constants
STATE_BALL_IN_PADDLE = 0
STATE_PLAYING = 1
STATE_GAME_WON = 2
STATE_GAME_OVER = 3
STATE_LEVEL_ONE = 4
STATE_LEVEL_TWO = 5
STATE_LEVEL_THREE = 6
STATE_LEVEL_ONE_WON = 7
STATE_LEVEL_TWO_WON = 8
STATE_LEVEL_THREE_WON = 9
# Initialising pygame
class Breakout:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("Breakout")
self.clock = pygame.time.Clock()
if pygame.font:
self.font = pygame.font.SysFont("impact", 20)
else:
self.font = None
self.init_game()
def init_game(self):
self.lives = 3
self.score = 0
self.state = STATE_BALL_IN_PADDLE
self.level_state = STATE_LEVEL_ONE
self.paddle = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def draw_level_one(self):
self.lives = 3
self.score = 0
self.level_state = STATE_LEVEL_ONE
self.state = STATE_BALL_IN_PADDLE
self.paddle = pygame.Rect(300, PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def draw_level_two(self):
self.lives = 3
self.score = 0
self.level_state = STATE_LEVEL_TWO
self.state = STATE_BALL_IN_PADDLE
self.paddle = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def draw_level_three(self):
self.lives = 3
self.score = 0
self.level_state = STATE_LEVEL_THREE
self.state = STATE_BALL_IN_PADDLE
self.paddle = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def create_bricks(self):
y_ofs = 50
self.bricks = []
for i in range(7):
x_ofs = 50
for j in range(8):
self.bricks.append(pygame.Rect(x_ofs,y_ofs,BRICK_WIDTH,BRICK_HEIGHT))
x_ofs += BRICK_WIDTH + 10
y_ofs += BRICK_HEIGHT + 5
def draw_bricks(self):
if self.level_state == STATE_LEVEL_ONE:
for brick in self.bricks:
pygame.draw.rect(self.screen, CYAN, brick)
elif self.level_state == STATE_LEVEL_TWO:
for brick in self.bricks:
pygame.draw.rect(self.screen, GREEN, brick)
elif self.level_state == STATE_LEVEL_THREE:
for brick in self.bricks:
pygame.draw.rect(self.screen, DARKRED, brick)
def check_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.paddle.left -= 7
if self.paddle.left < 0:
self.paddle.left = 0
if keys[pygame.K_RIGHT]:
self.paddle.left += 7
if self.paddle.left > MAX_PADDLE_X:
self.paddle.left = MAX_PADDLE_X
if keys[pygame.K_SPACE] and self.state == STATE_BALL_IN_PADDLE:
self.ball_vel = [5,-5]
self.state = STATE_PLAYING
elif keys[pygame.K_RETURN] and (self.state == STATE_GAME_OVER
or self.state == STATE_GAME_WON):
self.draw_level_one()
if keys[pygame.K_w]:
self.state = STATE_GAME_WON
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_l]:
self.state = STATE_GAME_OVER
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_1]:
self.draw_level_one()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_2]:
self.draw_level_two()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_3]:
self.draw_level_three()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if self.level_state == STATE_LEVEL_ONE_WON:
if keys[pygame.K_KP_ENTER]:
self.draw_level_two()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if self.level_state == STATE_LEVEL_TWO_WON:
if keys[pygame.K_KP_ENTER]:
self.draw_level_three()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if self.level_state == STATE_LEVEL_THREE_WON:
if keys[pygame.K_KP_ENTER]:
self.draw_level_one()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_ESCAPE]:
sys.exit()
def move_ball (self):
self.ball.left += self.ball_vel[0]
self.ball.top += self.ball_vel[1]
#bounds check
if self.ball.left <= 0:
self.ball.left = 0
self.ball_vel[0] = -self.ball_vel[0]
elif self.ball.left >= MAX_BALL_X:
self.ball.left = MAX_BALL_X
self.ball_vel[0] = -self.ball_vel[0]
if self.ball.top < 0:
self.ball.top = 0
self.ball_vel[1] = -self.ball_vel[1]
elif self.ball.top >= MAX_BALL_Y:
self.ball.top = MAX_BALL_Y
self.ball_vel[1] = -self.ball_vel[1]
def handle_collisions(self):
self.brick_counter = 0
for brick in self.bricks:
if self.ball.colliderect(brick):
#self.brick_counter += 1
self.score += 3
self.ball_vel[1] = -self.ball_vel[1]
#if self.brick_counter == 2:
self.bricks.remove(brick)
break
if len(self.bricks) == 0 or self.state == STATE_GAME_WON:
if self.level_state == STATE_LEVEL_ONE:
self.level_state == STATE_LEVEL_ONE_WON
elif self.level_state == STATE_LEVEL_TWO:
self.level_state == STATE_LEVEL_TWO_WON
elif self.level_state == STATE_LEVEL_THREE:
self.level_state == STATE_LEVEL_THREE_WON
if self.ball.colliderect(self.paddle):
self.ball.top = PADDLE_Y - BALL_DIAMETER
self.ball_vel[1] = -self.ball_vel[1]
elif self.ball.top > self.paddle.top:
self.lives -= 1
if self.lives > 0:
self.state = STATE_BALL_IN_PADDLE
else:
self.state = STATE_GAME_OVER
def show_stats(self):
if self.font:
font_surface = self.font.render("SCORE: " + str(self.score)
+ " LIVES: " + str(self.lives), False, WHITE)
self.screen.blit(font_surface, (205, 5))
def show_message(self, message):
if self.font:
size = self.font.size(message)
font_surface = self.font.render(message, False, WHITE)
x = (SCREEN_SIZE[0] - size[0]) /2
y = (SCREEN_SIZE[1] - size[1]) /2
self.screen.blit(font_surface, (x,y))
def run(self):
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.clock.tick(60)
self.screen.fill(BLACK)
self.check_input()
self.handle_collisions()
if self.state == STATE_PLAYING:
self.move_ball()
self.handle_collisions()
elif self.state == STATE_BALL_IN_PADDLE:
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
self.show_message("PRESS SPACE TO LAUNCH THE BALL")
elif self.state == STATE_GAME_OVER:
self.show_message("GAME OVER. PRESS ENTER TO PLAY AGAIN")
elif self.state == STATE_GAME_WON:
self.show_message("YOU WON! PRESS ENTER TO GO TO THE NEXT LEVEL")
self.draw_bricks()
#Draw paddle
pygame.draw.rect(self.screen, PINK, self.paddle)
#DraW ball
pygame.draw.circle(self.screen, WHITE, (self.ball.left + BALL_RADIUS,
self.ball.top + BALL_RADIUS), BALL_RADIUS)
self.show_stats()
pygame.display.flip()
if __name__ == "__main__":
Breakout().run()
看起来您正在使用 pygame.Rect 作为砖块对象,并使用单个 global 计数器来计算砖块被击中的次数。一旦任何一块砖被击中两次,那么计数器就不再能正常发挥作用。您真正应该做的是创建一个同时具有矩形和计数器的 Brick class,并更新该砖的计数器。
class Brick:
def __init__(self, rect):
self.rect = rect
self.hit_counter = 2
然后 self.bricks 将是这些对象的列表。
此外,您似乎假设砖块将从底部或顶部碰撞并导致速度的 y 分量反转。如果它从侧面碰撞,反弹看起来会有点奇怪,并且可能会让人感觉球是 "just passing through"。在发生碰撞时,您必须查看球相对于砖块的位置,然后决定是翻转速度的 x 分量还是翻转 y 分量。
类似这样的事情(抱歉,我可能没有完全匹配您的字段,但您明白了):
dx = brick.centerx - ball.centerx
dy = brick.centery - ball.centery
if abs(dx) > abs(dy):
self.ball_vel[0] *= -1
else:
self.ball_vel[1] *= -1
我正在制作一个 breakout 版本,虽然基础游戏可以运行,但我想制作关卡等。所以我想做的是在球击中 x 次之前,砖块不会被移除。
我试过添加一个计数器:
for brick in self.bricks:
if self.ball.colliderect(brick):
self.brick_counter += 1
self.score += 3
self.ball_vel[1] = -self.ball_vel[1]
if self.brick_counter == 2:
self.bricks.remove(brick)
break
但结果是球刚好穿过了砖块。
我也考虑过创建两层(或更多)砖块,但我不确定我将如何实现它。
完整代码如下:
import sys
import pygame
# Global variables is usually in the top of the document
SCREEN_SIZE = 750, 550
#OBJECT ATTRIBUTES
#PADDLE ATTRIBUTES
PADDLE_WIDTH = 54
PADDLE_HEIGHT = 10
MAX_PADDLE_X = SCREEN_SIZE[0] - PADDLE_WIDTH
PADDLE_Y = SCREEN_SIZE[1] - PADDLE_HEIGHT - 10
#BRICK ATTRIBUTES
BRICK_WIDTH = 75
BRICK_HEIGHT = 15
#BALL ATTRIBUTES
BALL_DIAMETER = 16
BALL_RADIUS = BALL_DIAMETER // 2
MAX_BALL_X = SCREEN_SIZE[0] - BALL_DIAMETER
MAX_BALL_Y = SCREEN_SIZE[1] - BALL_DIAMETER
#COLORS
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
CYAN = (0, 255, 255)
PINK = (255, 102, 255)
WHITE = (255, 255, 255)
NAVYBLUE = ( 60, 60, 100)
RED = (200, 0, 0)
DARKRED = (100, 0, 0)
ORANGE = (200, 100, 0)
DARKORANGE = (100, 50, 0)
YELLOW = (200, 200, 0)
DARKYELLOW = (100, 100, 0)
GREEN = ( 0, 200, 0)
DARKGREEN = ( 0, 100, 0)
BLUE = ( 0, 0, 200)
DARKBLUE = ( 0, 0, 100)
PURPLE = (200, 0, 200)
DARKPURPLE = (100, 0, 100)
RAINBOW = [(RED, DARKRED),(ORANGE,DARKORANGE),(YELLOW,DARKYELLOW),
(GREEN,DARKGREEN),(BLUE,DARKBLUE),(PURPLE,DARKPURPLE)]
BRICK_COLOR =(0, 255, 255)
# State constants
STATE_BALL_IN_PADDLE = 0
STATE_PLAYING = 1
STATE_GAME_WON = 2
STATE_GAME_OVER = 3
STATE_LEVEL_ONE = 4
STATE_LEVEL_TWO = 5
STATE_LEVEL_THREE = 6
STATE_LEVEL_ONE_WON = 7
STATE_LEVEL_TWO_WON = 8
STATE_LEVEL_THREE_WON = 9
# Initialising pygame
class Breakout:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("Breakout")
self.clock = pygame.time.Clock()
if pygame.font:
self.font = pygame.font.SysFont("impact", 20)
else:
self.font = None
self.init_game()
def init_game(self):
self.lives = 3
self.score = 0
self.state = STATE_BALL_IN_PADDLE
self.level_state = STATE_LEVEL_ONE
self.paddle = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def draw_level_one(self):
self.lives = 3
self.score = 0
self.level_state = STATE_LEVEL_ONE
self.state = STATE_BALL_IN_PADDLE
self.paddle = pygame.Rect(300, PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def draw_level_two(self):
self.lives = 3
self.score = 0
self.level_state = STATE_LEVEL_TWO
self.state = STATE_BALL_IN_PADDLE
self.paddle = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def draw_level_three(self):
self.lives = 3
self.score = 0
self.level_state = STATE_LEVEL_THREE
self.state = STATE_BALL_IN_PADDLE
self.paddle = pygame.Rect(300,PADDLE_Y,PADDLE_WIDTH,PADDLE_HEIGHT)
self.ball = pygame.Rect(300,PADDLE_Y - BALL_DIAMETER,BALL_DIAMETER,BALL_DIAMETER)
self.ball_vel = [5,-5]
self.create_bricks()
def create_bricks(self):
y_ofs = 50
self.bricks = []
for i in range(7):
x_ofs = 50
for j in range(8):
self.bricks.append(pygame.Rect(x_ofs,y_ofs,BRICK_WIDTH,BRICK_HEIGHT))
x_ofs += BRICK_WIDTH + 10
y_ofs += BRICK_HEIGHT + 5
def draw_bricks(self):
if self.level_state == STATE_LEVEL_ONE:
for brick in self.bricks:
pygame.draw.rect(self.screen, CYAN, brick)
elif self.level_state == STATE_LEVEL_TWO:
for brick in self.bricks:
pygame.draw.rect(self.screen, GREEN, brick)
elif self.level_state == STATE_LEVEL_THREE:
for brick in self.bricks:
pygame.draw.rect(self.screen, DARKRED, brick)
def check_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.paddle.left -= 7
if self.paddle.left < 0:
self.paddle.left = 0
if keys[pygame.K_RIGHT]:
self.paddle.left += 7
if self.paddle.left > MAX_PADDLE_X:
self.paddle.left = MAX_PADDLE_X
if keys[pygame.K_SPACE] and self.state == STATE_BALL_IN_PADDLE:
self.ball_vel = [5,-5]
self.state = STATE_PLAYING
elif keys[pygame.K_RETURN] and (self.state == STATE_GAME_OVER
or self.state == STATE_GAME_WON):
self.draw_level_one()
if keys[pygame.K_w]:
self.state = STATE_GAME_WON
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_l]:
self.state = STATE_GAME_OVER
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_1]:
self.draw_level_one()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_2]:
self.draw_level_two()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_3]:
self.draw_level_three()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if self.level_state == STATE_LEVEL_ONE_WON:
if keys[pygame.K_KP_ENTER]:
self.draw_level_two()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if self.level_state == STATE_LEVEL_TWO_WON:
if keys[pygame.K_KP_ENTER]:
self.draw_level_three()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if self.level_state == STATE_LEVEL_THREE_WON:
if keys[pygame.K_KP_ENTER]:
self.draw_level_one()
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
if keys[pygame.K_ESCAPE]:
sys.exit()
def move_ball (self):
self.ball.left += self.ball_vel[0]
self.ball.top += self.ball_vel[1]
#bounds check
if self.ball.left <= 0:
self.ball.left = 0
self.ball_vel[0] = -self.ball_vel[0]
elif self.ball.left >= MAX_BALL_X:
self.ball.left = MAX_BALL_X
self.ball_vel[0] = -self.ball_vel[0]
if self.ball.top < 0:
self.ball.top = 0
self.ball_vel[1] = -self.ball_vel[1]
elif self.ball.top >= MAX_BALL_Y:
self.ball.top = MAX_BALL_Y
self.ball_vel[1] = -self.ball_vel[1]
def handle_collisions(self):
self.brick_counter = 0
for brick in self.bricks:
if self.ball.colliderect(brick):
#self.brick_counter += 1
self.score += 3
self.ball_vel[1] = -self.ball_vel[1]
#if self.brick_counter == 2:
self.bricks.remove(brick)
break
if len(self.bricks) == 0 or self.state == STATE_GAME_WON:
if self.level_state == STATE_LEVEL_ONE:
self.level_state == STATE_LEVEL_ONE_WON
elif self.level_state == STATE_LEVEL_TWO:
self.level_state == STATE_LEVEL_TWO_WON
elif self.level_state == STATE_LEVEL_THREE:
self.level_state == STATE_LEVEL_THREE_WON
if self.ball.colliderect(self.paddle):
self.ball.top = PADDLE_Y - BALL_DIAMETER
self.ball_vel[1] = -self.ball_vel[1]
elif self.ball.top > self.paddle.top:
self.lives -= 1
if self.lives > 0:
self.state = STATE_BALL_IN_PADDLE
else:
self.state = STATE_GAME_OVER
def show_stats(self):
if self.font:
font_surface = self.font.render("SCORE: " + str(self.score)
+ " LIVES: " + str(self.lives), False, WHITE)
self.screen.blit(font_surface, (205, 5))
def show_message(self, message):
if self.font:
size = self.font.size(message)
font_surface = self.font.render(message, False, WHITE)
x = (SCREEN_SIZE[0] - size[0]) /2
y = (SCREEN_SIZE[1] - size[1]) /2
self.screen.blit(font_surface, (x,y))
def run(self):
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.clock.tick(60)
self.screen.fill(BLACK)
self.check_input()
self.handle_collisions()
if self.state == STATE_PLAYING:
self.move_ball()
self.handle_collisions()
elif self.state == STATE_BALL_IN_PADDLE:
self.ball.left = self.paddle.left + self.paddle.width / 2
self.ball.top = self.paddle.top - self.ball.height
self.show_message("PRESS SPACE TO LAUNCH THE BALL")
elif self.state == STATE_GAME_OVER:
self.show_message("GAME OVER. PRESS ENTER TO PLAY AGAIN")
elif self.state == STATE_GAME_WON:
self.show_message("YOU WON! PRESS ENTER TO GO TO THE NEXT LEVEL")
self.draw_bricks()
#Draw paddle
pygame.draw.rect(self.screen, PINK, self.paddle)
#DraW ball
pygame.draw.circle(self.screen, WHITE, (self.ball.left + BALL_RADIUS,
self.ball.top + BALL_RADIUS), BALL_RADIUS)
self.show_stats()
pygame.display.flip()
if __name__ == "__main__":
Breakout().run()
看起来您正在使用 pygame.Rect 作为砖块对象,并使用单个 global 计数器来计算砖块被击中的次数。一旦任何一块砖被击中两次,那么计数器就不再能正常发挥作用。您真正应该做的是创建一个同时具有矩形和计数器的 Brick class,并更新该砖的计数器。
class Brick:
def __init__(self, rect):
self.rect = rect
self.hit_counter = 2
然后 self.bricks 将是这些对象的列表。
此外,您似乎假设砖块将从底部或顶部碰撞并导致速度的 y 分量反转。如果它从侧面碰撞,反弹看起来会有点奇怪,并且可能会让人感觉球是 "just passing through"。在发生碰撞时,您必须查看球相对于砖块的位置,然后决定是翻转速度的 x 分量还是翻转 y 分量。
类似这样的事情(抱歉,我可能没有完全匹配您的字段,但您明白了):
dx = brick.centerx - ball.centerx
dy = brick.centery - ball.centery
if abs(dx) > abs(dy):
self.ball_vel[0] *= -1
else:
self.ball_vel[1] *= -1