Make your own BrickBreaker using python

In the following article we will learn how to create a simple brick breaker game using python

Tkinter Package:

Pyth-on offers multiple options for developing GUI(Graphical User Interface). Out of all the GUI methods, it is the most commonly used method. It is a standard python interface to the Tk GUI toolkit which is shipped with python. Python with tkinter gives the output is the fastest and easiest way to create  GUI.

Step 1: Creating a new file in gedit:-

gedit filename.py

Step 2: Importing the tkinter package: 

import tkinter as tk

If you have not installed the package install it using the following command .

sudo apt-get install python-tk python3-tk python-imaging-tk 

Step 3: Creating the main class:-  

class GameObject(object):
    def __init__(self, canvas, item):
        self.canvas = canvas
        self.item = item

    def get_position(self):
        return self.canvas.coords(self.item)

    def move(self, x, y):
        self.canvas.move(self.item, x, y)

    def delete(self):
        self.canvas.delete(self.item)

Note: 

The 'self' keyword is the instance of the class. By using the ‘self ‘ keyword we can access all the attributes and methods of class python.

The 'def' is the keyword used as a function header of all the function i.e It is used to define a function.

 The ‘__init__’  is a reserved method in python. It other words it is a constructor. When this method is called an object is created from the class and it allows the class to initialize the attributes of the class.

Step 4: Creating the Ball Class:-

This class will contain the following functions. This class will be the child class of the GameObject class.

  • The '__init__' function : It will contain the attributes of the ball like speed, radius and direction.
  • The 'update' function :  It will keep the track of the co-ordinates of the ball and constantly update them.
  • The 'collide' function : As the name suggests this function will compute the collsions between the ball and the bricks, the paddle as well as the edge of the screen
class Ball(GameObject):
    def __init__(self, canvas, x, y):
        self.radius = 10
        self.direction = [1, -1]
        self.speed = 10
        item = canvas.create_oval(x-self.radius, y-self.radius,
                                  x+self.radius, y+self.radius,
                                  fill='white')
        super(Ball, self).__init__(canvas, item)

    def update(self):
        coords = self.get_position()
        width = self.canvas.winfo_width()
        if coords[0] <= 0 or coords[2] >= width:
            self.direction[0] *= -1
        if coords[1] <= 0:
            self.direction[1] *= -1
        x = self.direction[0] * self.speed
        y = self.direction[1] * self.speed
        self.move(x, y)

    def collide(self, game_objects):
        coords = self.get_position()
        x = (coords[0] + coords[2]) * 0.5
        if len(game_objects) > 1:
            self.direction[1] *= -1
        elif len(game_objects) == 1:
            game_object = game_objects[0]
            coords = game_object.get_position()
            if x > coords[2]:
                self.direction[0] = 1
            elif x < coords[0]:
                self.direction[0] = -1
            else:
                self.direction[1] *= -1

        for game_object in game_objects:
            if isinstance(game_object, Brick):
                game_object.hit()

 Note: The ‘super’ keyword in python is used for calling all the inheritd methods which can be either from parent class or child class.

Step 5: Creating the Paddle Class:-

This class will also be the child class of the GameObejct class and will contain some functions initializing the attributes of the paddle and will contain the following functions.

  • The ‘__init__’ function : It will contain the basic attributes of the paddle like width and height
  • The ‘set_ball’ function : Using the ‘self’ keyword it will call all the properties of the ball and its basic use is to set the ball to the initial position
  • The ‘move’ function : This function will compute the co-ordinates of the paddle and then when the player moves the paddle it will change the co-ordinates according to the key pressed and will move the paddle accordingly.
class Paddle(GameObject):
    def __init__(self, canvas, x, y):
        self.width = 80
        self.height = 10
        self.ball = None
        item = canvas.create_rectangle(x - self.width / 2,
                                       y - self.height / 2,
                                       x + self.width / 2,
                                       y + self.height / 2,
                                       fill='yellow')
        super(Paddle, self).__init__(canvas, item)

    def set_ball(self, ball):
        self.ball = ball

    def move(self, offset):
        coords = self.get_position()
        width = self.canvas.winfo_width()
        if coords[0] + offset >= 0 and coords[2] + offset <= width:
            super(Paddle, self).move(offset, 0)
            if self.ball is not None:
                self.ball.move(offset, 0)

 Step 6: Creating the Brick Class:- 

This function will include their colour, position, height and width. It is also the child class of the GameObject Class.Before creating any function in the brick class define a variable which will contain the colours of the bricks. Further, it is the inherited class from the GameObject class and contains the following functions.

  • The ‘__init__’ function: As in all above classes, in this class also this function contains the basic attributes like width, height, etc of the bricks
  • The ‘hit’ function : It contains the logic of the ball hitting the brick. 
class Brick(GameObject):
    COLORS = {1: '#e74c3c', 2: '#3498db', 3: '#222222'}

    def __init__(self, canvas, x, y, hits):
        self.width = 75
        self.height = 20
        self.hits = hits
        color = Brick.COLORS[hits]
        item = canvas.create_rectangle(x - self.width / 2,
                                       y - self.height / 2,
                                       x + self.width / 2,
                                       y + self.height / 2,
                                       fill=color, tags='brick')
        super(Brick, self).__init__(canvas, item)

    def hit(self):
        self.hits -= 1
        if self.hits == 0:
            self.delete()
        else:
            self.canvas.itemconfig(self.item,
                                   fill=Brick.COLORS[self.hits])

Step 7: Creating the Game Class :

The class game is the inherited class of the tk.Frame class. It will contain the following functions:

  • The ‘__init__’ function : It contains the width, height the package of the canvas created and the logic of computing the lives of the player.
  • The ‘setup_game’ function : This function will show the text window at the starting of the game and will ask for an input from the user to start the game
  • The add_ball function : This function will first check for the ball on the GUI and will ad if the ball is not visible on canvas
  • The add_brick function : The function will add the bricks to the canvas
  • The draw_text function : The function contains the font and font size of the text to be displayed by at the starting of the game.
  • The update_lives_function : This particular function contains the logic of updating the status of the lives.
  • The start_game function : This function will start the game when the user hits the spacebar
  • The game_loop function : This function will keep track of all the bricks and if the number of bricks will be zero then will declare the user as a winner otherwise if the number of bricks are non-zero then after checking the status of the lives it will notify the user that the game is over
class Game(tk.Frame):
    def __init__(self, master):
        super(Game, self).__init__(master)
        self.lives = 3
        self.width = 610
        self.height = 400
        self.canvas = tk.Canvas(self, bg='#aaaaff',
                                width=self.width,
                                height=self.height,)
        self.canvas.pack()
        self.pack()

        self.items = {}
        self.ball = None
        self.paddle = Paddle(self.canvas, self.width/2, 326)
        self.items[self.paddle.item] = self.paddle
        for x in range(5, self.width - 5, 75):
            self.add_brick(x + 37.5, 50, 2)
            self.add_brick(x + 37.5, 70, 1)
            self.add_brick(x + 37.5, 90, 1)

        self.hud = None
        self.setup_game()
        self.canvas.focus_set()
        self.canvas.bind('<Left>',
                         lambda _: self.paddle.move(-10))
        self.canvas.bind('<Right>',
                         lambda _: self.paddle.move(10))

    def setup_game(self):
           self.add_ball()
           self.update_lives_text()
           self.text = self.draw_text(300, 200,
                                      'Press Space to start')
           self.canvas.bind('<space>', lambda _: self.start_game())

    def add_ball(self):
        if self.ball is not None:
            self.ball.delete()
        paddle_coords = self.paddle.get_position()
        x = (paddle_coords[0] + paddle_coords[2]) * 0.5
        self.ball = Ball(self.canvas, x, 310)
        self.paddle.set_ball(self.ball)

    def add_brick(self, x, y, hits):
        brick = Brick(self.canvas, x, y, hits)
        self.items[brick.item] = brick

    def draw_text(self, x, y, text, size='40'):
        font = ('Forte', size)
        return self.canvas.create_text(x, y, text=text,
                                       font=font)

    def update_lives_text(self):
        text = 'Lives: %s' % self.lives
        if self.hud is None:
            self.hud = self.draw_text(50, 20, text, 15)
        else:
            self.canvas.itemconfig(self.hud, text=text)

    def start_game(self):
        self.canvas.unbind('<space>')
        self.canvas.delete(self.text)
        self.paddle.ball = None
        self.game_loop()

    def game_loop(self):
        self.check_collisions()
        num_bricks = len(self.canvas.find_withtag('brick'))
        if num_bricks == 0: 
            self.ball.speed = None
            self.draw_text(300, 200, 'You win!')
        elif self.ball.get_position()[3] >= self.height: 
            self.ball.speed = None
            self.lives -= 1
            if self.lives < 0:
                self.draw_text(300, 200, 'You Lose!!! Game Over!')
            else:
                self.after(1000, self.setup_game)
        else:
            self.ball.update()
            self.after(50, self.game_loop)

Now you can play your favourit game in Odinub. 

Code :
Code Title :
brick.py
Code Language :
Python
0 Commenting Overall Comment