-
Book Overview & Buying
-
Table Of Contents
Python Game Programming By Example
By :
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:
self.check_collisions() to process the ball's collisions. We will see its implementation in the next code snippet..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.
Change the font size
Change margin width
Change background colour