import pygame
import random
pygame.init()
# Dimensions of the screen
WIDTH, HEIGHT = 600, 500
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
font = pygame.font.Font('freesansbold.ttf', 15)
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Block Breaker")
# to control the frame rate
clock = pygame.time.Clock()
FPS = 30
# Striker class
class Striker:
def __init__(self, posx, posy, width, height, speed, color):
self.posx, self.posy = posx, posy
self.width, self.height = width, height
self.speed = speed
self.color = color
# The rect variable is used to handle the placement
# and the collisions of the object
self.strikerRect = pygame.Rect(
self.posx, self.posy, self.width, self.height)
self.striker = pygame.draw.rect(screen,
self.color, self.strikerRect)
# Used to render the object on the screen
def display(self):
self.striker = pygame.draw.rect(screen,
self.color, self.strikerRect)
# Used to update the state of the object
def update(self, xFac):
self.posx += self.speed*xFac
# Restricting the striker to be in between the
# left and right edges of the screen
if self.posx <= 0:
self.posx = 0
elif self.posx+self.width >= WIDTH:
self.posx = WIDTH-self.width
self.strikerRect = pygame.Rect(
self.posx, self.posy, self.width, self.height)
# Returns the rect of the object
def getRect(self):
return self.strikerRect
# Block Class
class Block:
def __init__(self, posx, posy, width, height, color):
self.posx, self.posy = posx, posy
self.width, self.height = width, height
self.color = color
self.damage = 100
# The white blocks have the health of 200. So,
# the ball must hit it twice to break
if color == WHITE:
self.health = 200
else:
self.health = 100
# The rect variable is used to handle the placement
# and the collisions of the object
self.blockRect = pygame.Rect(
self.posx, self.posy, self.width, self.height)
self.block = pygame.draw.rect(screen, self.color,
self.blockRect)
# Used to render the object on the screen if and only
# if its health is greater than 0
def display(self):
if self.health > 0:
self.brick = pygame.draw.rect(screen,
self.color, self.blockRect)
# Used to decrease the health of the block
def hit(self):
self.health -= self.damage
# Used to get the rect of the object
def getRect(self):
return self.blockRect
# Used to get the health of the object
def getHealth(self):
return self.health
# Ball Class
class Ball:
def __init__(self, posx, posy, radius, speed, color):
self.posx, self.posy = posx, posy
self.radius = radius
self.speed = speed
self.color = color
self.xFac, self.yFac = 1, 1
self.ball = pygame.draw.circle(
screen, self.color, (self.posx,
self.posy), self.radius)
# Used to display the object on the screen
def display(self):
self.ball = pygame.draw.circle(
screen, self.color, (self.posx,
self.posy), self.radius)
# Used to update the state of the object
def update(self):
self.posx += self.xFac*self.speed
self.posy += self.yFac*self.speed
# Reflecting the ball if it touches
# either of the vertical edges
if self.posx <= 0 or self.posx >= WIDTH:
self.xFac *= -1
# Reflection from the top most edge of the screen
if self.posy <= 0:
self.yFac *= -1
# If the ball touches the bottom most edge of
# the screen, True value is returned
if self.posy >= HEIGHT:
return True
return False
# Resets the position of the ball
def reset(self):
self.posx = 0
self.posy = HEIGHT
self.xFac, self.yFac = 1, -1
# Used to change the direction along Y axis
def hit(self):
self.yFac *= -1
# Returns the rect of the ball. In this case,
# it is the ball itself
def getRect(self):
return self.ball
# Helper Functions
# Function used to check collisions between any two entities
def collisionChecker(rect, ball):
if pygame.Rect.colliderect(rect, ball):
return True
return False
# Function used to populate the blocks
def populateBlocks(blockWidth, blockHeight,
horizontalGap, verticalGap):
listOfBlocks = []
for i in range(0, WIDTH, blockWidth+horizontalGap):
for j in range(0, HEIGHT//2, blockHeight+verticalGap):
listOfBlocks.append(
Block(i, j, blockWidth, blockHeight,
random.choice([WHITE, GREEN])))
return listOfBlocks
# Once all the lives are over, this function waits until
# exit or space bar is pressed and does the corresponding action
def gameOver():
gameOver = True
while gameOver:
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
return True
# Game Manager
def main():
running = True
lives = 3
score = 0
scoreText = font.render("score", True, WHITE)
scoreTextRect = scoreText.get_rect()
scoreTextRect.center = (20, HEIGHT-10)
livesText = font.render("Lives", True, WHITE)
livesTextRect = livesText.get_rect()
livesTextRect.center = (120, HEIGHT-10)
striker = Striker(0, HEIGHT-50, 100, 20, 10, WHITE)
strikerXFac = 0
ball = Ball(0, HEIGHT-150, 7, 5, WHITE)
blockWidth, blockHeight = 40, 15
horizontalGap, verticalGap = 20, 20
listOfBlocks = populateBlocks(
blockWidth, blockHeight, horizontalGap, verticalGap)
# Game loop
while running:
screen.fill(BLACK)
screen.blit(scoreText, scoreTextRect)
screen.blit(livesText, livesTextRect)
scoreText = font.render("Score : " + str(score), True, WHITE)
livesText = font.render("Lives : " + str(lives), True, WHITE)
# If all the blocks are destroyed, then we repopulate them
if not listOfBlocks:
listOfBlocks = populateBlocks(
blockWidth, blockHeight, horizontalGap, verticalGap)
# All the lives are over. So, the gameOver() function is called
if lives <= 0:
running = gameOver()
while listOfBlocks:
listOfBlocks.pop(0)
lives = 3
score = 0
listOfBlocks = populateBlocks(
blockWidth, blockHeight, horizontalGap, verticalGap)
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
strikerXFac = -1
if event.key == pygame.K_RIGHT:
strikerXFac = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or
event.key == pygame.K_RIGHT:
strikerXFac = 0
# Collision check
if(collisionChecker(striker.getRect(),
ball.getRect())):
ball.hit()
for block in listOfBlocks:
if(collisionChecker(block.getRect(), ball.getRect())):
ball.hit()
block.hit()
if block.getHealth() <= 0:
listOfBlocks.pop(listOfBlocks.index(block))
score += 5
# Update
striker.update(strikerXFac)
lifeLost = ball.update()
if lifeLost:
lives -= 1
ball.reset()
print(lives)
# Display
striker.display()
ball.display()
for block in listOfBlocks:
block.display()
pygame.display.update()
clock.tick(FPS)
if __name__ == "__main__":
main()
pygame.quit()