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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
#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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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() |