Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Python Game Programming By Example

You're reading from   Python Game Programming By Example A pragmatic guide for developing your own games with Python

Arrow left icon
Product type Paperback
Published in Sep 2015
Publisher
ISBN-13 9781785281532
Length 230 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Toc

Starting the game

Finally, we have built the functionality needed to run the game loop—the logic required to update the ball's position according to the rebounds, and restart the game if the player loses one life.

Now we can add the following methods to our Game class to complete the development of our game:

    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, 'Game Over')
            else:
                self.after(1000, self.setup_game)
        else:
            self.ball.update()
            self.after(50, self.game_loop)

The start_game method, which we left unimplemented in a previous section, is responsible for unbinding the Spacebar input key so that the player cannot start the game twice, detaching the ball from the paddle, and starting the game loop.

Step by step, the game_loop method does the following:

  • It calls self.check_collisions() to process the ball's collisions. We will see its implementation in the next code snippet.
  • If the number of bricks left is zero, it means that the player has won, and a congratulations text is displayed.
  • Suppose the ball has reached the bottom of the canvas:
    • Then, the player loses one life. If the number of lives left is zero, it means that the player has lost, and the Game Over text is shown. Otherwise, the game is reset
  • Otherwise, this is what happens:
    • The position of the ball is updated according to its speed and direction, and the game loop is called again. The .after(delay, callback) method on a Tkinter widget sets a timeout to invoke a function after a delay in milliseconds. Since this statement will be executed when the game is not over yet, this creates the loop necessary to execute this logic continuously:
          def check_collisions(self):
              ball_coords = self.ball.get_position()
              items = self.canvas.find_overlapping(*ball_coords)
              objects = [self.items[x] for x in items \
                     if x in self.items]
              self.ball.collide(objects)

The check_collisions method links the game loop with the ball collision method. Since Ball.collide receives a list of game objects and canvas.find_overlapping returns a list of colliding items with a given position, we use the dictionary of items to transform each canvas item into its corresponding game object.

Remember that the items attribute of the Game class contains only those canvas items that can collide with the ball. Therefore, we need to pass only the items contained in this dictionary. Once we have filtered the canvas items that cannot collide with the ball, such as the text displayed in the top-left corner, we retrieve each game object by its key.

With list comprehensions, we can create the required list in one simple statement:

objects = [self.items[x] for x in items if x in self.items]

The basic syntax of list comprehensions is the following:

new_list = [expr(elem) for elem in collection]

This means that the new_list variable will be a list whose elements are the result of applying the expr function to each elem in the list collection.

We can filter the elements to which the expression will be applied by adding an if clause:

new_list = [expr(elem) for elem in collection if elem is not None]

This syntax is equivalent to the following loop:

new_list = []
for elem in collection:
    if elem is not None:
        new_list.append(elem)

In our case, the initial list is the list of colliding items, the if clause filters the items that are not contained in the dictionary, and the expression applied to each element retrieves the game object associated with the canvas item. The collide method is called with this list as a parameter, and the logic for the game loop is completed.

You have been reading a chapter from
Python Game Programming By Example
Published in: Sep 2015
Publisher:
ISBN-13: 9781785281532
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime