Предыдущая статья — Введение в объектно-ориентированное программирование (ООП).
Добро пожаловать в следующую часть нашей серии статей про объектно-ориентированное программирование. В этой статье мы построим окружение для нашего объекта при помощи библиотеки Pygame.
Вот наш код из предыдущей статьи:
class Blob: def __init__(self, color): self.x = random.randrange(0, WIDTH) self.y = random.randrange(0, HEIGHT) self.size = random.randrange(4,8) self.color = color def move(self): self.move_x = random.randrange(-1,2) self.move_y = random.randrange(-1,2) self.x += self.move_x self.y += self.move_y if self.x < 0: self.x = 0 elif self.x > WIDTH: self.x = WIDTH if self.y < 0: self.y = 0 elif self.y > HEIGHT: self.y = HEIGHT
Итак, мы с нашей Кляксой отлично стартовали. Давайте теперь добавим код для среды, в которой эта Клякса будет существовать:
import pygame import random WIDTH = 800 HEIGHT = 600 WHITE = (255, 255, 255) BLUE = (0, 0, 255) RED = (255, 0, 0) game_display = pygame.display.set_mode((WIDTH,HEIGHT)) pygame.display.set_caption('Blob World') clock = pygame.time.Clock()
Это просто базовый стартовый код и константы. Цвета — это кортежи RGB. Если вы хотите более подробно ознакомиться с библиотекой Pygame, то обратитесь к ее документации. Но, скорей всего, все необходимое вы найдете в наших статьях. Также в наших видео есть дополнительная информация.
Теперь напишем начало функции, которая обрабатывает отрисовку окружения:
def draw_environment(): game_display.fill(WHITE) pygame.display.update()
Очевидно, что в обработке графики задействовано много математики и тому подобного, но процесс, с наибольшей вероятностью способный вызвать зависание, обновляет значения пикселей на экране.
Обычно процесс для простой игры выглядит примерно так:
- запустить логику игры и вычисления,
- нарисовать следующий кадр в фоновом режиме, фактически не показывая его,
- обновить отдельные части, а затем, когда он будет полностью обновлен и готов —
- отправить его на экран.
В нашем случае мы просто заполняем экран белым цветом, а затем используем метод .update
, чтобы вывести на экран последний кадр.
Теперь напишем функцию main()
и условие для прекращения игры:
def main(): while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() draw_environment() clock.tick(60) if __name__ == '__main__': main()
В нашем случае это будет выполняться бесконечно, пока не будет запущена процедура pygame.quit
(пользователь нажимает клавишу «X», чтобы закрыть окно). При каждом проходе в цикле while True мы проверяем событие выхода, затем отрисовываем экран и с помощью функции clock
определяем кадровую частоту (FPS). В данном примере мы установили ее равной 60 кадрам в секунду. Это не значит, что она всегда будет именно такой, просто она не превысит данное значение.
PyGame работает на вашем процессоре и, как вы только что узнали, по умолчанию будет работать на одном ядре, так что это не идеальная стартовая среда. Преобразование PyGame в многопроцессорный движок — довольно сложная задача, и мы не собираемся делать этого здесь. Но мы можем проследить за тем, чтобы наша фактическая игровая логика работала в отдельном процессе или нескольких процессах, и чтобы PyGame, по крайней мере, получала все ресурсы одного ядра.
На данный момент мы можем запустить следующий код:
import pygame import random WIDTH = 800 HEIGHT = 600 WHITE = (255, 255, 255) BLUE = (0, 0, 255) RED = (255, 0, 0) game_display = pygame.display.set_mode((WIDTH,HEIGHT)) pygame.display.set_caption('Blob World') clock = pygame.time.Clock() class Blob: def __init__(self, color): self.x = random.randrange(0, WIDTH) self.y = random.randrange(0, HEIGHT) self.size = random.randrange(4,8) self.color = color def move(self): self.move_x = random.randrange(-1,2) self.move_y = random.randrange(-1,2) self.x += self.move_x self.y += self.move_y if self.x < 0: self.x = 0 elif self.x > WIDTH: self.x = WIDTH if self.y < 0: self.y = 0 elif self.y > HEIGHT: self.y = HEIGHT def draw_environment(): game_display.fill(WHITE) pygame.display.update() def main(): while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() draw_environment() clock.tick(60) if __name__ == '__main__': main()
Но пока у нас есть только белое игровое поле. Мы хотим, чтобы наша клякса тоже там была! Давайте создадим объект Blob
и добавим его в наше окружение.
Для начала нам нужно создать объект Blob, потому что пока мы создали только соответствующий класс. Мы можем это сделать прямо в главной функции:
def main(): red_blob = Blob(RED) ...
В данном случае мы указываем один аргумент, который требуется классу Blob
, а именно цвет RED
, как было описано в методе __init__
. Поэтому данный объект класса Blob
будет красным. Теперь давайте передадим этот объект Blob
в функцию draw_environment
:
draw_environment(red_blob)
И определим саму функцию следующим образом:
def draw_environment(blob): game_display.fill(WHITE) pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size) pygame.display.update()
Функция Game_display.fill (WHITE)
заполнит весь экран белым цветом, затем мы рисуем кляксу в виде круга, а затем обновляем отображение.
Запустив данный код, мы получим красную кляксу на экране:
А что если мы захотим, чтобы наша клякса танцевала? Тогда мы просто добавим в нашу функцию draw_environment
метод blob.move()
. Мы можем это сделать в любом месте, но добавим его в конец:
def draw_environment(blob): game_display.fill(WHITE) pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size) pygame.display.update() blob.move()
Наш полнй код на данный момент времени:
import pygame import random WIDTH = 800 HEIGHT = 600 WHITE = (255, 255, 255) BLUE = (0, 0, 255) RED = (255, 0, 0) game_display = pygame.display.set_mode((WIDTH,HEIGHT)) pygame.display.set_caption('Blob World') clock = pygame.time.Clock() class Blob: def __init__(self, color): self.x = random.randrange(0, WIDTH) self.y = random.randrange(0, HEIGHT) self.size = random.randrange(4,8) self.color = color def move(self): self.move_x = random.randrange(-1,2) self.move_y = random.randrange(-1,2) self.x += self.move_x self.y += self.move_y if self.x < 0: self.x = 0 elif self.x > WIDTH: self.x = WIDTH if self.y < 0: self.y = 0 elif self.y > HEIGHT: self.y = HEIGHT def draw_environment(blob): game_display.fill(WHITE) pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size) pygame.display.update() blob.move() def main(): red_blob = Blob(RED) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() draw_environment(red_blob) clock.tick(60) if __name__ == '__main__': main()
Теперь при запуске этого кода у нас будет прекрасная, извивающаяся клякса!
Следующая статья — Введение в объектно-ориентированное программирование: много клякс.