Pygame入門 ブロック崩しゲームを作る(途中) ボールと衝突したブロックを消す しかし、ボールはブロックに当たっても跳ね返らない

マウスの左クリックで開始します

import pygame
import sys

SCREEN = pygame.Rect(0, 0, 400, 400)
FPS = 30

WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

BALL_SIZE = 20

PADDLE_WIDTH = 60
PADDLE_HEIGHT = 5
PADDLE_POS_Y = SCREEN.bottom - 30

BLOCK_ROW = 5
BLOCK_COLUMN = 6
BLOCK_MARGIN = 10
BLOCK_WIDTH = ((SCREEN.width - BLOCK_MARGIN) / BLOCK_COLUMN) - BLOCK_MARGIN
BLOCK_HEIGHT = 20

class Ball(pygame.sprite.Sprite):
    def __init__(self, pos, speed):
        pygame.sprite.Sprite.__init__(self, self.containers)
        x, y = pos
        vx, vy = speed
        self.image = pygame.Surface((BALL_SIZE, BALL_SIZE))
        self.image.fill(WHITE)
        pygame.draw.circle(self.image, RED, self.image.get_rect().center, BALL_SIZE / 2)
        self.rect = pygame.Rect(x, y, BALL_SIZE, BALL_SIZE)
        self.vx = vx
        self.vy = vy
        self.update = self.start #これにより、updateメソッドが呼び出されるとstartメソッドが実行される

    def start(self):
        #Ballの初期X座標をPaddleのX座標にする
        self.rect.centerx = paddle.rect.centerx

        #マウスの左クリックによりBallを動かし始める
        if pygame.mouse.get_pressed()[0]:
            self.update = self.move #これにより、updateメソッドが呼び出されるとmoveメソッドが実行される

    def move(self):
        #Ballを移動させる
        self.rect.move_ip(self.vx, self.vy)
        #Paddleに当たったら跳ね返る
        if self.rect.colliderect(paddle.rect):
            self.vy = -self.vy
            self.rect.bottom = paddle.rect.top
        #画面の左端か右端に当たったら跳ね返る
        if self.rect.left < SCREEN.left or SCREEN.right < self.rect.right:
            self.vx = -self.vx
        #画面の上端に当たったら跳ね返る
        if self.rect.top < SCREEN.top:
            self.vy = -self.vy
        #画面の下端に当たったら止まる
        if SCREEN.bottom < self.rect.bottom:
            self.vx = 0
            self.vy = 0

        self.rect = self.rect.clamp(SCREEN) #SCREENから出ないようにする

class Paddle(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.image = pygame.Surface((PADDLE_WIDTH, PADDLE_HEIGHT))
        self.image.fill(GREEN)
        self.rect = pygame.Rect(0, PADDLE_POS_Y, PADDLE_WIDTH, PADDLE_HEIGHT)

    def update(self):
        self.rect.centerx = pygame.mouse.get_pos()[0] #Paddleの真ん中のX座標をマウスのX座標にする
        self.rect = self.rect.clamp(SCREEN) #SCREENから出ないようにする

class Block(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self, self.containers)
        x, y = pos
        self.image = pygame.Surface((BLOCK_WIDTH, BLOCK_HEIGHT))
        self.image.fill(BLUE)
        self.rect = pygame.Rect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT)

#main
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode(SCREEN.size)

sprite_group = pygame.sprite.Group() #すべてのスプライトの更新と描画を行うためのグループ
block_group = pygame.sprite.Group() #BallとBlockの衝突判定とBlockの削除を行うためのグループ
Ball.containers = sprite_group #これにより、Ballインスタンスが自動でsprite_groupに追加される
Paddle.containers = sprite_group #これにより、Paddleインスタンスが自動でsprite_groupに追加される
Block.containers = sprite_group, block_group #これにより、Blockインスタンスが自動でsprite_groupとblock_groupに追加される

ball = Ball((200, 150), (6, 6))
paddle = Paddle()
#Blockの作成
for r in range(BLOCK_ROW):
    for c in range(BLOCK_COLUMN):
        block_x =  BLOCK_MARGIN + (BLOCK_WIDTH + BLOCK_MARGIN) * c
        block_y = BLOCK_MARGIN + (BLOCK_HEIGHT + BLOCK_MARGIN) * r
        Block((block_x, block_y))

while True:
    #Ballと衝突したBlockを削除する
    #ballスプライトとblock_groupに属している各Blockスプライトの衝突を判定してくれる
    #3つ目の引数をTrueにするとballと衝突したBlockがblock_groupから削除される
    #それによりballと衝突したBlockは画面から消える。(画面描画はsprite_group.draw(screen)により行われているため。)
    pygame.sprite.spritecollide(ball, block_group, True)

    sprite_group.update()
    screen.fill(WHITE)
    sprite_group.draw(screen)
    pygame.display.update()
    clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()