⬆️ ⬇️

Making games in Python 3 and Pygame: Part 2

image


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



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



Class TextObject



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

')

The TextObject class creates a font object. It renders the text on a separate text surface, which is then copied (rendered) onto the main surface. An interesting aspect of TextObject is that it does not have any fixed text. It gets the text_func() function that is called each 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 keeping track of which text objects display points and lives and update their text each time they change. This is a handy 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 the main window



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



Then, the main loop is executed, which constantly fills the screen with a monotone gray and calls the tick() timer method 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) 


Use background image



Usually the solid color of the background 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, it loads the background image before the main loop using the pygame.image.load() function. Then, instead of filling the screen with color, it blits (copies the bits) of the image onto the screen at 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. In the pygame.draw module pygame.draw are functions for drawing the following shapes:





All objects in Breakout (with the exception of text) are simple shapes. Let's examine the draw () method of various Breakout objects.



Bricks drawing



Bricks are just rectangles. In Pygame, there is a pygame.draw.rect() function that gets the surface, color, and a Rect object (left and top coordinates, width and height) and a rendering 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 the Brick class is a subclass of GameObject and gets all its properties, but also has a color that processes itself (because there may be game objects that have several colors). We will not consider the special_effect 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. In Pygame, there is a pygame.draw.circle() function that receives the color, center, radius, and optional width parameter, which defaults to zero. As in the pygame.draw.rect() function, if the width is zero, then a solid circle is drawn. Ball is also a subclass of GameObject.



Since the ball always moves (as opposed to bricks), it also has a speed that is passed to the base GameObject class to process. The Ball class has a slight difference - the x and y parameters denote its center, and the x and y parameters passed to the base GameObject class are 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) 


Draw a racket



A racket is another rectangle that moves left and right in response to the 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 is. Here is the corresponding code:



 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 section, we learned about the TextObject class and how to render text on the screen. We also learned how to draw objects: bricks, a ball and a racket.



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

Source: https://habr.com/ru/post/347170/



All Articles