Creating Games in Python 3 and Pygame: Part 2

Original author: Gigi Sayfan
  • Transfer
  • Tutorial
image

(The rest of the tutorial: first , third , fourth , fifth .)

In the second of five parts of the tutorial on creating games using Python 3 and Pygame, we will look at the class TextObjectused to render text on the screen. We will create the main window, including the background image, and then learn how to draw objects: bricks, ball and racket.

Class TextObject


The class is TextObjectdesigned to display text on the screen. We can conclude that from the point of view of design, it should be a subclass of the class GameObject, because it is also a visual object and it also needs to be moved sometimes. But I did not want to introduce a deep class hierarchy, in which all the Breakout text displayed on the screen remained unchanged.

The class TextObjectcreates a font object. It renders the text on a separate text surface, which is then copied (rendered) to the main surface. An interesting aspect TextObjectis that it does not have any fixed text. It gets a function text_func()called every time it is rendered.

This allows us to update the display of lives and points in Breakout, simply by creating a function that returns current lives and points, rather than tracking which text objects display points and lives and updating their text each time they change. This is a convenient trick from functional programming, and in large games it allows you to maintain the convenience and accuracy of the program.

import pygame
class TextObject:
    def __init__(self, 
                 x, 
                 y, 
                 text_func, 
                 color, 
                 font_name, 
                 font_size):
        self.pos = (x, y)
        self.text_func = text_func
        self.color = color
        self.font = pygame.font.SysFont(font_name, font_size)
        self.bounds = self.get_surface(text_func())
    def draw(self, surface, centralized=False):
        text_surface, self.bounds = \
            self.get_surface(self.text_func())
        if centralized:
            pos = (self.pos[0] - self.bounds.width // 2,
                   self.pos[1])
        else:
            pos = self.pos
        surface.blit(text_surface, pos)
    def get_surface(self, text):
        text_surface = self.font.render(text, 
                                        False, 
                                        self.color)
        return text_surface, text_surface.get_rect()
    def update(self):
        pass

Creating a main window


Games on Pygame run in windows. You can even make them run in full screen mode. Now I will tell you how to display an empty Pygame window. You will see many of the elements that we discussed earlier. init()Pygame is called first , and then the main drawing surface and timer are created.

Then the main loop is executed, which constantly fills the screen with a solid gray color and calls the timer method tick()with a frame rate.

import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
while True:
    screen.fill((192, 192, 192))
    pygame.display.update()
    clock.tick(60)

Using a background image


Usually a plain background color does not look very interesting. Pygame works very well with images. For Breakout, I found a curious photograph of real space taken by NASA. The code is very simple. First, before the main loop, it loads the background image using the function pygame.image.load(). Then, instead of filling the screen with color, it performs blitting (copying of bits) of the image on the screen to the position (0,0). As a result, an image is displayed on the screen.

import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
background_image = pygame.image.load('images/background.jpg')
while True:
    screen.blit(background_image, (0, 0))
    pygame.display.update()
    clock.tick(60)


Drawing shapes


Pygame can draw anything. The module pygame.drawhas functions for rendering the following figures:

  • rectangle
  • polygon (polygon)
  • circle (circle)
  • ellipse (ellipse)
  • arcs (arc)
  • line segment
  • segments (lines)
  • smooth line (anti-aliased line)
  • anti-aliased lines

All objects in Breakout (excluding text) are simple shapes. Let's learn the draw () method of various Breakout objects.

Brick drawing


Bricks are just rectangles. Pygame has a function pygame.draw.rect()that takes a surface, color, and a Rect object (left and top coordinate, width and height) and renders a rectangle. If the optional width parameter is greater than zero, then it draws a path. If the width is zero (the default value), then draws a solid rectangle.

It is worth noting that a class Brickis a subclass GameObjectand receives all its properties, but also has a color that it processes on its own (because there may be game objects that have several colors). special_effectWe will not consider the field yet.

import pygame
from game_object import GameObject
class Brick(GameObject):
    def __init__(self, x, y, w, h, color, special_effect=None):
        GameObject.__init__(self, x, y, w, h)
        self.color = color
        self.special_effect = special_effect
    def draw(self, surface):
        pygame.draw.rect(surface, self.color, self.bounds)

Ball drawing


The ball in Breakout is just a circle. Pygame has a function pygame.draw.circle()that receives color, center, radius, and an additional width parameter, which is zero by default. As in the function pygame.draw.rect(), if the width is zero, then a solid circle is drawn. Ball is also a subclass of GameObject.

Since the ball always moves (unlike bricks), it also has a speed that is transmitted for processing to the base class GameObject. The Ball class has a slight difference - the x and y parameters indicate its center, and the x and y parameters passed to the base class GameObjectare the upper left corner of the bounding box. To convert the center to the upper left corner, just subtract the radius.

import pygame
from game_object import GameObject
class Ball(GameObject):
    def __init__(self, x, y, r, color, speed):
        GameObject.__init__(self, 
                            x - r, 
                            y - r, 
                            r * 2, 
                            r * 2, 
                            speed)
        self.radius = r
        self.diameter = r * 2
        self.color = color
    def draw(self, surface):
        pygame.draw.circle(surface, 
                           self.color, 
                           self.center, 
                           self.radius)

Racket drawing


A racket is another rectangle that moves left and right in response to a player pressing the arrow keys. This means that the position of the racket in different frames may differ, but in the process of drawing it is just a rectangle, which should be rendered in the current position, whatever it may be. Here's what the corresponding code looks like:

import pygame
import config as c
from game_object import GameObject
class Paddle(GameObject):
    def __init__(self, x, y, w, h, color, offset):
        GameObject.__init__(self, x, y, w, h)
        self.color = color
        self.offset = offset
        self.moving_left = False
        self.moving_right = False
    def draw(self, surface):
        pygame.draw.rect(surface, self.color, self.bounds)

Conclusion


In this part, we learned about the TextObject class and how to render text on the screen. We also learned how to draw objects: bricks, ball and racket.

In the third part, we will learn how event processing works and how Pygame allows us to intercept events and respond to them (keystrokes, mouse movement and mouse clicks). We will also consider such elements of the gameplay as the movement of the ball, setting its speed and moving the racket.

Also popular now: