Brick Storm!
Breakout
Paddle, ball, wall of bricks, the 1976 classic in Pygame. Bounce physics, paddle spin, rows of bricks from nested loops, lives and a win state. Part 2 next episode adds power-ups!
Paddle, ball, wall of bricks, the 1976 classic in Pygame. Bounce physics, paddle spin, rows of bricks from nested loops, lives and a win state. Part 2 next episode adds power-ups!
import pygameimport pygame, pygame.init()pygame.init(), the window and the while runningwhile running game loop. If you're starting here or need that template, grab it in one click: Episode 1 full template โ ยท Python Cheatsheet โFresh project with a smooth, clamped paddle at the bottom.
paddle = pygame.Rect(295, 480, 110, 14)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle.x -= 8
if keys[pygame.K_RIGHT]:
paddle.x += 8
paddle.x = max(0, min(700 - paddle.width, paddle.x))paddle = pygame.Rect(295, 480, 110, 14)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle.x -= 8
if keys[pygame.K_RIGHT]:
paddle.x += 8
paddle.x = max(0, min(700 - paddle.width, paddle.x))
A ball that moves diagonally and bounces off three walls.
ball = pygame.Rect(340, 300, 14, 14)
bvx, bvy = 4, -4
ball.x += bvx
ball.y += bvy
if ball.left <= 0 or ball.right >= 700:
bvx = -bvx
if ball.top <= 0:
bvy = -bvyball = pygame.Rect(340, 300, 14, 14)
bvx, bvy = 4, -4
ball.x += bvx
ball.y += bvy
if ball.left <= 0 or ball.right >= 700:
bvx = -bvx
if ball.top <= 0:
bvy = -bvy
if ball.left <= 0 or ball.right >= if ball.left <= 0 or ball.right >= :
bvx = :
bvx =
if ball.top <= 0:
bvy =
if ball.top <= 0:
bvy =
Rebound off the paddle with player-controlled angle.
if ball.colliderect(paddle) and bvy > 0:
bvy = -bvy
offset = ball.centerx - paddle.centerx
bvx = offset // 12
if bvx == 0:
bvx = 1if ball.colliderect(paddle) and bvy > 0:
bvy = -bvy
offset = ball.centerx - paddle.centerx
bvx = offset // 12
if bvx == 0:
bvx = 1
Generate 5 rows ร 10 columns of bricks with row colours.
colours = [(248,113,113),(251,146,60),(250,204,21),(74,222,128),(96,165,250)]
bricks = []
for row in range(5):
for col in range(10):
bricks.append({
"rect": pygame.Rect(col*68 + 12, row*26 + 50, 64, 22),
"row": row
})
for b in bricks:
pygame.draw.rect(screen, colours[b["row"]], b["rect"])colours = [(248,113,113),(251,146,60),(250,204,21),(74,222,128),(96,165,250)]
bricks = []
for row in range(5):
for col in range(10):
bricks.append({
"rect": pygame.Rect(col*68 + 12, row*26 + 50, 64, 22),
"row": row
})
for b in bricks:
pygame.draw.rect(screen, colours[b["row"]], b["rect"])
for row in range(for row in range():
for col in range():
for col in range():
bricks.append({"rect": pygame.Rect(col*):
bricks.append({"rect": pygame.Rect(col* + 12, row*26 + 50, 64, 22), "row": row}) + 12, row*26 + 50, 64, 22), "row": row})
Destroy bricks on contact with a satisfying bounce and scaled score.
score = 0
for b in bricks[:]:
if ball.colliderect(b["rect"]):
bricks.remove(b)
score += (5 - b["row"]) * 10
bvy = -bvy
breakscore = 0
for b in bricks[:]:
if ball.colliderect(b["rect"]):
bricks.remove(b)
score += (5 - b["row"]) * 10
bvy = -bvy
break
Finish the game: lives, game over, and the you-cleared-it screen.
lives = 3
state = "PLAY"
if ball.top > 520:
lives -= 1
ball.center = (350, 300)
bvx, bvy = 4, -4
if lives == 0:
state = "LOSE"
if len(bricks) == 0:
state = "WIN"lives = 3
state = "PLAY"
if ball.top > 520:
lives -= 1
ball.center = (350, 300)
bvx, bvy = 4, -4
if lives == 0:
state = "LOSE"
if len(bricks) == 0:
state = "WIN"
if ball.top > 520:
lives -= 1
ball.if ball.top > 520:
lives -= 1
ball. = (350, 300)
if lives == = (350, 300)
if lives == :
state = :
state =
A clamped paddle, a bouncing ball, paddle-spin steering, a colour-banded brick wall, break-and-score, three lives and win/lose screens , one file. Save it as game.pygame.py, run python game.pypython game.py, and play. This is also the base Episode 6 builds power-ups on. Stuck? Compare your file against this.
import pygame
pygame.init()
screen = pygame.display.set_mode((700, 520))
pygame.display.set_caption("Brick Breaker")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 32)
big_font = pygame.font.SysFont(None, 64)
colours = [(248, 113, 113), (251, 146, 60), (250, 204, 21), (74, 222, 128), (96, 165, 250)]
def build_bricks():
b = []
for row in range(5):
for col in range(10):
b.append({"rect": pygame.Rect(col*68 + 12, row*26 + 50, 64, 22), "row": row})
return b
paddle = pygame.Rect(295, 480, 110, 14)
ball = pygame.Rect(340, 300, 14, 14)
bvx, bvy = 4, -4
bricks = build_bricks()
score = 0
lives = 3
state = "PLAY"
def reset():
global paddle, ball, bvx, bvy, bricks, score, lives, state
paddle = pygame.Rect(295, 480, 110, 14)
ball = pygame.Rect(340, 300, 14, 14)
bvx, bvy = 4, -4
bricks = build_bricks()
score = 0
lives = 3
state = "PLAY"
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_r and state != "PLAY":
reset()
if state == "PLAY":
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle.x -= 8
if keys[pygame.K_RIGHT]:
paddle.x += 8
paddle.x = max(0, min(700 - paddle.width, paddle.x))
ball.x += bvx
ball.y += bvy
if ball.left <= 0 or ball.right >= 700:
bvx = -bvx
if ball.top <= 0:
bvy = -bvy
if ball.colliderect(paddle) and bvy > 0:
bvy = -bvy
offset = ball.centerx - paddle.centerx
bvx = offset // 12
if bvx == 0:
bvx = 1
for b in bricks[:]:
if ball.colliderect(b["rect"]):
bricks.remove(b)
score += (5 - b["row"]) * 10
bvy = -bvy
break
if ball.top > 520:
lives -= 1
ball.center = (350, 300)
bvx, bvy = 4, -4
if lives == 0:
state = "LOSE"
if len(bricks) == 0:
state = "WIN"
# draw
screen.fill((25, 30, 60))
for b in bricks:
pygame.draw.rect(screen, colours[b["row"]], b["rect"])
pygame.draw.rect(screen, (255, 119, 0), paddle)
pygame.draw.ellipse(screen, (255, 255, 255), ball)
screen.blit(font.render("Score: " + str(score), True, (255, 255, 255)), (12, 8))
screen.blit(font.render("Lives: " + str(max(0, lives)), True, (255, 255, 255)), (560, 8))
if state != "PLAY":
text = "YOU WIN!" if state == "WIN" else "GAME OVER"
msg = big_font.render(text, True, (255, 209, 102))
screen.blit(msg, msg.get_rect(center=(350, 235)))
sub = font.render("Press R to play again", True, (255, 255, 255))
screen.blit(sub, sub.get_rect(center=(350, 290)))
pygame.display.flip()
clock.tick(60)
pygame.quit()import pygame
pygame.init()
screen = pygame.display.set_mode((700, 520))
pygame.display.set_caption("Brick Breaker")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 32)
big_font = pygame.font.SysFont(None, 64)
colours = [(248, 113, 113), (251, 146, 60), (250, 204, 21), (74, 222, 128), (96, 165, 250)]
def build_bricks():
b = []
for row in range(5):
for col in range(10):
b.append({"rect": pygame.Rect(col*68 + 12, row*26 + 50, 64, 22), "row": row})
return b
paddle = pygame.Rect(295, 480, 110, 14)
ball = pygame.Rect(340, 300, 14, 14)
bvx, bvy = 4, -4
bricks = build_bricks()
score = 0
lives = 3
state = "PLAY"
def reset():
global paddle, ball, bvx, bvy, bricks, score, lives, state
paddle = pygame.Rect(295, 480, 110, 14)
ball = pygame.Rect(340, 300, 14, 14)
bvx, bvy = 4, -4
bricks = build_bricks()
score = 0
lives = 3
state = "PLAY"
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_r and state != "PLAY":
reset()
if state == "PLAY":
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle.x -= 8
if keys[pygame.K_RIGHT]:
paddle.x += 8
paddle.x = max(0, min(700 - paddle.width, paddle.x))
ball.x += bvx
ball.y += bvy
if ball.left <= 0 or ball.right >= 700:
bvx = -bvx
if ball.top <= 0:
bvy = -bvy
if ball.colliderect(paddle) and bvy > 0:
bvy = -bvy
offset = ball.centerx - paddle.centerx
bvx = offset // 12
if bvx == 0:
bvx = 1
for b in bricks[:]:
if ball.colliderect(b["rect"]):
bricks.remove(b)
score += (5 - b["row"]) * 10
bvy = -bvy
break
if ball.top > 520:
lives -= 1
ball.center = (350, 300)
bvx, bvy = 4, -4
if lives == 0:
state = "LOSE"
if len(bricks) == 0:
state = "WIN"
# draw
screen.fill((25, 30, 60))
for b in bricks:
pygame.draw.rect(screen, colours[b["row"]], b["rect"])
pygame.draw.rect(screen, (255, 119, 0), paddle)
pygame.draw.ellipse(screen, (255, 255, 255), ball)
screen.blit(font.render("Score: " + str(score), True, (255, 255, 255)), (12, 8))
screen.blit(font.render("Lives: " + str(max(0, lives)), True, (255, 255, 255)), (560, 8))
if state != "PLAY":
text = "YOU WIN!" if state == "WIN" else "GAME OVER"
msg = big_font.render(text, True, (255, 209, 102))
screen.blit(msg, msg.get_rect(center=(350, 235)))
sub = font.render("Press R to play again", True, (255, 255, 255))
screen.blit(sub, sub.get_rect(center=(350, 290)))
pygame.display.flip()
clock.tick(60)
pygame.quit()