This tutorial is the second tutorial in a series of five Pygame tutorials:
- Breakout Tutorial 1: Getting Started
- Breakout Tutorial 2: Adding the Paddle
- Breakout Tutorial 3: Controlling the Paddle
- Breakout Tutorial 4: Adding a Bouncing Ball
- Breakout Tutorial 5: Adding a Brick Wall
- Extra: Pygame How To’s?
The final stage of our tutorial focuses on adding a brick wall and a scoring system to our Breakout game:
- The player will score a point if the ball bounces against a brick.
- The player will lose a life if the ball bounces against the bottom edge of the screen.
- Both the score and number of lives will be displayed at the top of the screen.
- A “Level Complete” message will be displayed if all bricks have been removed.
The final code for the main.py is provided below. We made several changes to the code as follows:
- On line 6 we import the Brick class. (Code provided in the brick.py tab)
- On lines 39 to 57 we create three rows of bricks and add them to a group called all_bricks.
- On lines 93 to 103 we take a life away when the ball hit the bottom edge of the screen. If the number of lives reaches zero, we display a “Game Over” message..
- On lines 114 to 129 we detect if the ball hits a brick. If so we remove the brick (using the kill() method) and increment the score by one.
main.pypaddle.pyball.pybrick.py
#Import the pygame library and initialise the game engine
import pygame
#Let's import the Paddle Class & the Ball Class
from paddle import Paddle
from ball import Ball
from brick import Brick
pygame.init()
# Define some colors
WHITE = (255,255,255)
DARKBLUE = (36,90,190)
LIGHTBLUE = (0,176,240)
RED = (255,0,0)
ORANGE = (255,100,0)
YELLOW = (255,255,0)
score = 0
lives = 3
# Open a new window
size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Breakout Game")
#This will be a list that will contain all the sprites we intend to use in our game.
all_sprites_list = pygame.sprite.Group()
#Create the Paddle
paddle = Paddle(LIGHTBLUE, 100, 10)
paddle.rect.x = 350
paddle.rect.y = 560
#Create the ball sprite
ball = Ball(WHITE,10,10)
ball.rect.x = 345
ball.rect.y = 195
all_bricks = pygame.sprite.Group()
for i in range(7):
brick = Brick(RED,80,30)
brick.rect.x = 60 + i* 100
brick.rect.y = 60
all_sprites_list.add(brick)
all_bricks.add(brick)
for i in range(7):
brick = Brick(ORANGE,80,30)
brick.rect.x = 60 + i* 100
brick.rect.y = 100
all_sprites_list.add(brick)
all_bricks.add(brick)
for i in range(7):
brick = Brick(YELLOW,80,30)
brick.rect.x = 60 + i* 100
brick.rect.y = 140
all_sprites_list.add(brick)
all_bricks.add(brick)
# Add the paddle and the ball to the list of sprites
all_sprites_list.add(paddle)
all_sprites_list.add(ball)
# The loop will carry on until the user exits the game (e.g. clicks the close button).
carryOn = True
# The clock will be used to control how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while carryOn:
# --- Main event loop
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
carryOn = False # Flag that we are done so we exit this loop
#Moving the paddle when the use uses the arrow keys
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle.moveLeft(5)
if keys[pygame.K_RIGHT]:
paddle.moveRight(5)
# --- Game logic should go here
all_sprites_list.update()
#Check if the ball is bouncing against any of the 4 walls:
if ball.rect.x>=790:
ball.velocity[0] = -ball.velocity[0]
if ball.rect.x<=0:
ball.velocity[0] = -ball.velocity[0]
if ball.rect.y>590:
ball.velocity[1] = -ball.velocity[1]
lives -= 1
if lives == 0:
#Display Game Over Message for 3 seconds
font = pygame.font.Font(None, 74)
text = font.render("GAME OVER", 1, WHITE)
screen.blit(text, (250,300))
pygame.display.flip()
pygame.time.wait(3000)
#Stop the Game
carryOn=False
if ball.rect.y<40:
ball.velocity[1] = -ball.velocity[1]
#Detect collisions between the ball and the paddles
if pygame.sprite.collide_mask(ball, paddle):
ball.rect.x -= ball.velocity[0]
ball.rect.y -= ball.velocity[1]
ball.bounce()
#Check if there is the ball collides with any of bricks
brick_collision_list = pygame.sprite.spritecollide(ball,all_bricks,False)
for brick in brick_collision_list:
ball.bounce()
score += 1
brick.kill()
if len(all_bricks)==0:
#Display Level Complete Message for 3 seconds
font = pygame.font.Font(None, 74)
text = font.render("LEVEL COMPLETE", 1, WHITE)
screen.blit(text, (200,300))
pygame.display.flip()
pygame.time.wait(3000)
#Stop the Game
carryOn=False
# --- Drawing code should go here
# First, clear the screen to dark blue.
screen.fill(DARKBLUE)
pygame.draw.line(screen, WHITE, [0, 38], [800, 38], 2)
#Display the score and the number of lives at the top of the screen
font = pygame.font.Font(None, 34)
text = font.render("Score: " + str(score), 1, WHITE)
screen.blit(text, (20,10))
text = font.render("Lives: " + str(lives), 1, WHITE)
screen.blit(text, (650,10))
#Now let's draw all the sprites in one go. (For now we only have 2 sprites!)
all_sprites_list.draw(screen)
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
#Once we have exited the main program loop we can stop the game engine:
pygame.quit()
The code for the Paddle class remains unchanged.
import pygame
BLACK = (0,0,0)
class Paddle(pygame.sprite.Sprite):
#This class represents a paddle. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the paddle, its width and height.
# Set the background color and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(BLACK)
self.image.set_colorkey(BLACK)
# Draw the paddle (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def moveLeft(self, pixels):
self.rect.x -= pixels
#Check that you are not going too far (off the screen)
if self.rect.x < 0:
self.rect.x = 0
def moveRight(self, pixels):
self.rect.x += pixels
#Check that you are not going too far (off the screen)
if self.rect.x > 700:
self.rect.x = 700
The code for the Ball class remains unchanged.
import pygame
from random import randint
BLACK = (0, 0, 0)
class Ball(pygame.sprite.Sprite):
#This class represents a ball. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the ball, its width and height.
# Set the background color and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(BLACK)
self.image.set_colorkey(BLACK)
# Draw the ball (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
self.velocity = [randint(4,8),randint(-8,8)]
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def update(self):
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
def bounce(self):
self.velocity[0] = -self.velocity[0]
self.velocity[1] = randint(-8,8)
This is the code for the new Brick class, to be saved in a new file called brick.py.
import pygame
BLACK = (0,0,0)
class Brick(pygame.sprite.Sprite):
#This class represents a brick. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the brick, and its x and y position, width and height.
# Set the background color and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(BLACK)
self.image.set_colorkey(BLACK)
# Draw the brick (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()




