Основы PyGame¶
Pygame — библиотека, предназначенная для разработки мультимедийных приложений с графическим интерфейсом, например игр.
Документация, обучающие материалы и дополнительная информация доступна разработчикам на сайте проекта: https://www.pygame.org/docs/
Начало работы¶
Начнем знакомство с библиотекой непосредственно с разбора примера простого приложения:
import pygame import sys pygame.init() screen = pygame.display.set_mode((1200, 800)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit()
В первую очередь импортируем модуль pygame в наш файл с исходным кодом:
import pygame
Затем вызываем функцию init() для подготовки модулей pygame к работе:
pygame.init()
После этого создаем графическое окно, передав в качестве аргумента в функцию set_mode() его разрешение в виде пары целых чисел. В свою очередь функция вернет нам объект типа Surface, используемый для представления изображений:
screen = pygame.display.set_mode((1200, 800))
Далее, запускаем основной цикл программы, в котором, среди всех событий, происходящих в нашем приложении, перехватываем событие закрытия основного графического окна пользователем:
while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit()
После того как ожидаемое событие наступило, завершаем работу с библиотекой pygame вызовом функции pygame.quit() и нашей программы вызовом функции exit() из модуля sys .
Рисование геометрических фигур¶
Разместим в окне нашего приложения прямоугольник. Прямоугольные объекты представлены типом Rect :
Rect(left, top, width, height) Rect((left, top), (width, height))
Для создания объекта этого типа нам необходимо указать координаты левого верхнего угла прямоугольника и длины его сторон:
r = Rect(0, 0, 100, 200)
Обратите внимание, что начало координат (0, 0) находится в левом верхнем углу окна.
В библиотеке pygame функции отображения геометрических фигур находятся в модуле draw . Нарисуем прямоугольник c помощью функции rect() :
rect(Surface, color, Rect, width=0) -> Rect
Для этого передадим в функцию в качестве аргументов поверхность, на которой мы размещаем прямоугольник, его цвет, сам прямоугольник и толщину линии — стороны прямоугольника. Если толщина равна нулю прямоугольник закрашивается сплошным цветом.
Рассмотрим готовый пример:
import pygame import sys pygame.init() screen = pygame.display.set_mode((1000, 800)) r = pygame.Rect(50, 50, 100, 200) pygame.draw.rect(screen, (255, 0, 0), r, 0) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() pygame.display.flip()
Обратите внимание на последнюю строку нашей программы. На самом деле графические объекты которые мы хотим разместить на основном экране сначала попадают в специальный буфер. Чтобы отобразить изменения стали видны вызываем функцию flip() .
Функции для рисования графических фигур¶
pygame.draw. rect ( Surface, color, Rect, width=0 ) ¶
Нарисовать прямоугольник Rect на поверхности Surface , цветом color . Если толщина линии width равна нулю, прямоугольник закрашивается.
pygame.draw. line ( Surface, color, start_pos, end_pos, width=1 ) ¶
Нарисовать линию на поверхности Surface , цветом color , с началом в точке start_pos , концом в точке end_pos и толщиной линии width.
pygame.draw. lines ( Surface, color, closed, pointlist, width=1 ) ¶
Нарисовать линию, соединяющую точки из последовательности pointlist на поверхности Surface , цветом color , с толщиной линии width . Каждая точка представлена парой координат. Если параметр closed равен True , конечная точка соединяется с начальной.
Нарисовать окружность на поверхности Surface, цветом color , с центром в точке pos и радиусом radius . Если толщина линии width равна нулю, окружность закрашивается.
Нарисовать эллипс, ограниченный прямоугольником Rect , на поверхности Surface , цветом color . Если толщина линии width равна нулю, эллипс закрашивается.
pygame.draw. polygon ( Surface, color, pointlist, width=0 ) ¶
Нарисовать многоугольник по точкам из последовательности pointlist на поверхности Surface , цветом color , с толщиной линии width . Каждая точка представлена парой координат. Если толщина линии width равна нулю многоугольник закрашивается.
Цвет¶
Цвета в библиотеке pygame представлены в соответствии с моделью RGB: https://ru.wikipedia.org/wiki/RGB
Значение для цвета можно задать тройкой чисел, каждое из которых лежит в диапазоне от 0 до 255. Первое значение в последовательности определяет, какое количество красного содержится в данном оттенке, второе — зеленого, третье — голубого. Чем меньше значение числа, тем темнее будет оттенок. Например, красный цвет можно представить как (255, 0, 0), белый как (255, 255, 255), а черный как (0, 0, 0).
Помимо этого, в модуле color из библиотеки pygame содержится словарь THECOLORS, ключами которого являются названия различных цветовых оттенков. Подключить его можно с помощью команды:
from pygame.color import THECOLORS
Закрасим основной экран c помощью метода fill() :
screen = pygame.display.set_mode((1200, 800)) screen.fill(THECOLORS['orange'])
Текст и шрифты¶
При работе с текстом мы будем использовать шрифты — группы символов объединенных по стилистическому или иному признаку. Шрифты в библиотеке pygame представлены типом Font
Чтобы создать объект Font на основе имеющегося в системе шрифта вызовем следующую функцию:
SysFont(name, size, bold=False, italic=False)
С помощью параметра name передаем в функцию имя шрифта, параметр size — размер шрифта в пунктах. Параметры bold и italic отвечают за начертание шрифта.
Список имеющихся в системе шрифтов можно получить с помощью функции get_fonts() :
pygame.font.get_fonts() -> list of strings
Далее, с помощью метода render() нашего объекта типа Font получаем изображение с текстом, которое передаем на вход методу blit() для отрисовки на нашем основном экране:
screen = pygame.display.set_mode(size) screen.fill(THECOLORS['white']) font = pygame.font.SysFont('couriernew', 40) text = font.render(str('HELLO'), True, THECOLORS['green']) screen.blit(text, (50, 50))
Текст размещается в на основном экране по координатам (50, 50)
Задания¶
1. Используя функции для работы с графикой библиотеки pygame, нарисуйте дом с квадратным основанием и треугольной крышей.
2. Используя функции для работы с графикой библиотеки pygame, нарисуйте белый флаг с олимпийскими кольцами.
3. Разработайте программу, которая разбивает основное игровое окно на клетки заданного размера.
4. Доработайте программу так, чтобы в каждой клетке был записан её порядковый номер.
5. Доработайте в программу возможность закрашивания клетки с произвольным номером случайным цветом. Номера клеток которые необходимо закрасить считывать из файла.
© Copyright Revision d00c0df4 .
Built with Sphinx using a theme provided by Read the Docs.
Read the Docs v: latest
Versions latest Downloads html On Read the Docs Project Home Builds Free document hosting provided by Read the Docs.
Дополнительные главы
Библиотека pygame создана для разработки игр. Она проста в освоении и позволяет быстро создавать прототипы игр. Средства библиотеки pygame также позволяют создавать интерактивные визуализации и приложения с простым графическим пользовательским интерфейсом. В этом разделе будут рассмотрены основные инструменты библиотеки pygame.
Основной цикл
Интерактивность программ с pygame обеспечивается благодаря основному циклу. В этом цикле происходит обработка событий, таких как нажатие кнопок клавиатуры, и отрисовка изображений. Вот так выглядит программа, которая рисует круг и завершается при нажатии Escape или кнопки закрытия окна:
import sys import pygame # Инициализация pygame pygame.init() # Размер окна screen = pygame.display.set_mode((300, 300)) # Заголовок окна pygame.display.set_caption('Blue Circle') while True: # Задаем цвет фона screen.fill((255, 255, 224)) # Рисуем круг pygame.draw.circle(screen, (50, 50, 200), (150, 150), 75) # Обновляем экран pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit()
Функция pygame.draw.circle принимает следующие аргументы:
- surface — объект типа Surface — поверхность, на которой будет отрисован круг. В данном случае это основное окно программы.
- color — кортеж из трех целых чисел или объект типа Color — цвет фигуры в представлении RGB.
- center — кортеж из двух целых чисел — координаты центра круга в пикселях. Координаты отсчитываются от левого верхнего угла.
- radius — радиус круга в пикселях.
- width — ширина кольца в пикселях — необязательный параметр. Если параметр задан, то будет нарисовано кольцо, а не круг.
Функция pygame.draw.circle возвращает объект Rect — прямоугольник, содержащий нарисованный объект. Это нам еще пригодится, когда мы будем организовывать взаимодействие с кругом.

Вывод текста
За работу с текстом в pygame отвечает модуль font. Перед его использованием необходимо выполнить инициализацию
pygame.font.init()
Функция pygame.font.SysFont создает объект типа Font , который может отрисовывать текст:
font = pygame.font.SysFont(name=font, size=20) surf = font.render( 'Click on the circle', antialias=True, color=(0, 0, 0)) screen.blit(surf, (70, 260))
Функция render создает объект типа Surface с отрисованным текстом. Параметр antialias управляет сглаживанием текста.
Метод Surface.blit отрисовывает одну поверхность на другой. Мы ей воспользовались чтобы отрисовать поверхность с текстом в основном окне. В результате получаем следующее:

Обработка событий
Сделаем так, чтобы круг менял цвет при нажатии на него мышкой:
def get_color(): idx = 0 colors = [ (50, 50, 200), (50, 200, 50), (200, 50, 50) ] while True: yield colors[idx % len(colors)] idx += 1 colors = get_color() color = next(colors) while True: # . circ_rect = pygame.draw.circle(screen, color, (150, 150), 75) for event in pygame.event.get(): # . if event.type == pygame.MOUSEBUTTONDOWN: if circ_rect.collidepoint(event.pos): color = next(colors)
Атрибут pos возвращает координаты нажатия курсора, метод Rect.collidepoint возвращает True , если координаты лежат внутри прямоугольника.
Графические примитивы и маски
Модуль pygame.draw содержит инструменты для отрисовки различных графических примитивов:
- pygame.draw.polygon(surface, color, pointlist, width)
- pygame.draw.line(surface, color, start_point, end_point, width)
- pygame.draw.lines(surface, color, closed, pointlist, width)
- pygame.draw.circle(surface, color, center_point, radius, width)
- pygame.draw.ellipse(surface, color, bounding_rectangle, width)
- pygame.draw.rect(surface, color, rectangle_tuple, width)
В текущем виде программа реагирует на нажатие мышки внутри квадрата, описанного вокруг круга. Для проверки попадания координаты внутрь круга можно использовать инструменты модуля pygame.mask :
while True: # . circ_surf = pygame.Surface((150, 150), pygame.SRCALPHA, 32)\ .convert_alpha() circ_rect = pygame.draw.circle(circ_surf, color, (75, 75), 75) screen.blit(circ_surf, (75, 75)) circ_mask = pygame.mask.from_surface(circ_surf) for event in pygame.event.get(): # . if event.type == pygame.MOUSEBUTTONDOWN: rpos = (event.pos[0] - 75, event.pos[1] - 75) if circ_rect.collidepoint(rpos) and\ circ_mask.get_at(rpos): color = next(colors)
Сначала мы создали прозрачную поверхность, на которой нарисовали круг. Затем на основе этой поверхности создали битовую маску, соответствующую пикселям поверхности. Маска выделяет все непрозрачные пиксели поверхности. При проверке попадания координаты внутрь круга используется метод mask.get_at , возвращающий значение маски в заданной позиции. Поскольку круг нарисован на поверхности circ_surf , а не в главной поверхности, то проверка положения выполняется в локальных координатах на поверхности circ_surf .
Работа с растровыми файлами
Модуль pygame.image позволяет открывать изображение из файла и сохранять поверхности (объекты типа Surface ) в файл. Поместим логотип pygame в наше окно:
logo_surf = pygame.image.load('figs/logo_lofi.png') screen.blit(logo_surf, (60, 10))
В результате получаем:

Чтобы сохранить содержимое поверхности в файл, нужно вызвать
pygame.image.save(screen, 'screen.png')
Частота обновления
Наш учебный пример не содержит двигающихся объектов, поэтому нет никакой разницы, с какой частотой выполняется основной цикл. Ситуация меняется, если в программе есть анимация. В этом случае скорость движения прямо зависит от скорости работы цикла. Модуль pygame.time содержит инструменты для работы со временем. Например, класс pygame.time.Clock позволяет ограничить количество обновлений в секунду:
frames_per_second = 30 clock = pygame.time.Clock() while True: # . clock.tick(frames_per_second)
Другой вариант — функция pygame.time.wait , которая выполняет задержку на определенное количество миллисекунд. Заметим, что использовать задержку имеет смысл даже в нашем примере. Действительно, достаточно малая задержка не будет видна пользователю, но позволит значительно уменьшить нагрузку на процессор. Полный код нашего примера выглядит так:
import sys import pygame # Инициализация pygame pygame.init() pygame.font.init() # Размер окна screen = pygame.display.set_mode((300, 300)) # Заголовок окна pygame.display.set_caption("Blue Circle") font = pygame.font.SysFont(name='arial', size=20) def get_color(): idx = 0 colors = [ (50, 50, 200), (50, 200, 50), (200, 50, 50) ] while True: yield colors[idx % len(colors)] idx += 1 text = 'Click on the circle' colors = get_color() color = next(colors) logo_surf = pygame.image.load('figs/logo_lofi.png') delay = 100 while True: # Задаем цвет фона screen.fill((255, 255, 224)) # Рисуем круг circ_surf = pygame.Surface((150, 150), pygame.SRCALPHA, 32)\ .convert_alpha() circ_rect = pygame.draw.circle(circ_surf, color, (75, 75), 75) screen.blit(circ_surf, (75, 75)) circ_mask = pygame.mask.from_surface(circ_surf) # Рисуем текст font_surf = font.render(text, True, (0, 0, 0)) screen.blit(font_surf, (70, 260)) # Рисуем лого pygame screen.blit(logo_surf, (60, 10)) # Обновляем экран pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() elif event.type == pygame.MOUSEBUTTONDOWN: rpos = (event.pos[0] - 75, event.pos[1] - 75) if circ_rect.collidepoint(rpos) and\ circ_mask.get_at(rpos): color = next(colors) pygame.time.wait(delay)
Резюме
В этом разделе мы обсудили основные инструменты библиотеки pygame.
Источники
- Документация pygame
- PyGame: A Primer on Game Programming in Python
- Python pygame – The Full Tutorial
- Game loop
- Game Loop pattern
- dr0id pygame tutorials
- Введение
- Настройка рабочей среды
- Язык C++
- Язык Python
- Дополнительные главы
- Графика и GUI с библиотекой pygame
- Виртуальная машина
Класс Rect
Еще одни ключевым классом в Pygame является Rect . Его экземпляры представляют собой прямоугольные области. Они не имеют графического представления в окне игры. Ценность класса заключается в свойствах и методах, позволяющих управлять размещением поверхностей, выполнять проверку их перекрытия и др.
Rect’ы можно передавать в функцию pygame.display.update() . В этом случае будут обновляться только соответствующие им области.
Экземпляры Rect создаются не только напрямую от класса. Однако начнем с этого варианта.
import pygame as pg import sys sc = pg.display.set_mode((400, 400)) rect1 = pg.Rect((0, 0, 30, 30)) rect2 = pg.Rect((30, 30, 30, 30)) print(rect1.bottomright) # (30, 30) print(rect2.bottomright) # (60, 60) rect2.move_ip(10, 10) print(rect2.topleft) # (40, 40) rect1.union_ip(rect2) print(rect1.width) # 70 while 1: for i in pg.event.get(): if i.type == pg.QUIT: sys.exit()
В конструктор класса Rect передаются четыре числа – координаты x и y , ширина и высота. Мы создаем два квадрата со сторонами в 30 пикселей. Верхний левый угол первого находится в точке (0, 0), второго – (30, 30).
У объектов Rect есть более десятка свойств, связанных с их координатами и размерами. Свойство bottomright одно из них, в нем хранится координата нижнего правого угла. Понятно, что если второй квадрат начинается в точке (30, 30) и его сторона равна 30, то нижний правый угол будет в точке (60, 60).
Кроме свойств, у объектов Rect есть множество методов. Метод move_ip() смещает прямоугольную область по оси x (первый аргумент) и y (второй аргумент) на указанное количество пикселей. В данном случае если второй прямоугольник смещается на 10 пикселей по обоим осям, то его левый верхний угол окажется в точке (40, 40).
Метод union_ip() присоединяет к тому прямоугольнику, к которому применяется, другой – который передается аргументом. Когда мы отодвинули второй прямоугольник на 10 пикселей, то область, заключающая в себе оба, уже будет шириной 70 пикселей, а не 60.
Методы, у которых есть суффикс _ip , изменяют тот экземпляр Rect , к которому применяются. Есть аналогичные методы без _ip (например, move() , union() ), которые возвращают новый экземпляр, т. е. старый остается без изменений.
В метод blit() можно передавать не координаты места размещения Surface , а экземпляр Rect . Метод blit() сам возьмет из Rect координаты его верхнего левого угла:
import pygame as pg import sys GREEN = (200, 255, 200) YELLOW = (220, 200, 0) WHITE = (255, 255, 255) sc = pg.display.set_mode((300, 300)) sc.fill(GREEN) surf1 = pg.Surface((200, 200)) surf1.fill(YELLOW) surf2 = pg.Surface((100, 100)) surf2.fill(WHITE) rect = pg.Rect((70, 20, 0, 0)) surf1.blit(surf2, rect) sc.blit(surf1, rect) pg.display.update() while 1: for i in pg.event.get(): if i.type == pg.QUIT: sys.exit()

Мы размещаем желтую поверхность на зеленой, а белую – на желтой. В обоих случаях – в координатах (70, 20). Однако в каждом случае точка берется относительно своей родительской поверхности.
Еще один момент, на который надо обратить внимание. Прямоугольная область была определена нулевой размерностью. При этом поверхности отобразились соответственно своим собственным размерам. Это значит, что поверхности не располагаются внутри rect’ов. Они к ним никакого отношения не имеют. Из прямоугольников blit() взял только координаты.
С другой стороны, экземпляры Rect предназначены для хранения не только координат, но и размеров поверхностей. Размеры в основном нужны для проверки коллизий. В большинстве случаев сначала создается поверхность. Далее с нее снимается «маска», т. е. создается экземпляр Rect , который будет иметь те же размеры, что и она. Все дальнейшее «взаимодействие» поверхности с другими объектами (размещение, проверка столкновений и вхождений) происходит через «связанный» с ней Rect .
import pygame import sys GREEN = (200, 255, 200) WHITE = (255, 255, 255) sc = pygame.display.set_mode((300, 300)) surf = pygame.Surface((100, 100)) surf.fill(WHITE) rect = surf.get_rect() # создается экземпляр Rect print(surf.get_width()) # 100 print(rect.width) # 100 print(rect.x, rect.y) # 0 0 while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() sc.fill(GREEN) sc.blit(surf, rect) pygame.display.update() rect.x += 1 pygame.time.delay(20)
Метод поверхности get_rect() возвращает экземпляр Rect , ширина и высота которого совпадают с таковыми поверхности. В примере метод get_width() возвращает ширину поверхности, также выводится ширина прямоугольника ( rect.width ), чтобы показать, что они равны.
Если в get_rect() не передавать аргументы, то верхний левый угол экземпляра Rect будет в точке (0, 0).
В цикле мы изменяем координату x прямоугольной области, после чего передаем уже измененный rect в метод blit() . В результате поверхность будет двигаться.
Польза заключается в том, что нам не нужно вводить множество переменных для хранения координат и размеров. Вместо этого для каждой поверхности заводится свой Rect , который включает необходимые значения и ряд полезных методов.
В get_rect() можно передавать именованные аргументы, являющиеся свойствами Rect , и устанавливать им значения. Например, surf.get_rect(topleft=(100, 50)) вернет прямоугольник, чей левый угол будет в точке (100, 50), а размер совпадать с размерами surf . Выражение surf.get_rect(centerx=100) вернет прямоугольник, координата x центра которого будет иметь значение 100. При этом остальные координаты будут вычислены, исходя из размеров поверхности.
Перепишем программу с двумя ракетами из предыдущего урока, используя экземпляры Rect .
import pygame import sys WIN_WIDTH = 800 WIN_HEIGHT = 600 WHITE = (255, 255, 255) BLACK = (0, 0, 0) class Rocket: width_rocket = 20 height_rocket = 50 def __init__(self, surface, color): self.surf = surface self.color = color self.x = surface.get_width()//2 - Rocket.width_rocket//2 self.y = surface.get_height() def fly(self): pygame.draw.rect(self.surf, self.color, (self.x, self.y, Rocket.width_rocket, Rocket.height_rocket)) self.y -= 3 if self.y -Rocket.height_rocket: self.y = self.surf.get_height() sc = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) rect_left = pygame.Rect((0, 0), (WIN_WIDTH//2, WIN_HEIGHT)) rect_right = pygame.Rect((WIN_WIDTH//2, 0), (WIN_WIDTH//2, WIN_HEIGHT)) surf_left = pygame.Surface((rect_left.width, rect_left.height)) surf_left.fill(WHITE) surf_right = pygame.Surface((rect_right.width, rect_right.height)) sc.blit(surf_left, rect_left) sc.blit(surf_right, rect_right) rocket_left = Rocket(surf_left, BLACK) rocket_right = Rocket(surf_right, WHITE) pygame.display.update() active_left = False active_right = False while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.MOUSEBUTTONUP: if rect_left.collidepoint(i.pos): active_left = True active_right = False elif rect_right.collidepoint(i.pos): active_right = True active_left = False if active_left: surf_left.fill(WHITE) rocket_left.fly() sc.blit(surf_left, rect_left) pygame.display.update(rect_left) elif active_right: surf_right.fill(BLACK) rocket_right.fly() sc.blit(surf_right, rect_right) pygame.display.update(rect_right) pygame.time.delay(20)
Главное, на что здесь следует обратить внимание, – вызов функции pygame.display.update() с аргументом-прямоугольником. Таким образом, на каждой итерации главного цикла while в памяти компьютера «перерисовывается» только часть окна, что экономит его ресурсы.
rect_left = pygame.Rect((0, 0), (WIN_WIDTH//2, WIN_HEIGHT)) rect_right = pygame.Rect((WIN_WIDTH//2, 0), (WIN_WIDTH//2, WIN_HEIGHT))
Создаются два экземпляра Rect . Левый начинается в верхнем левом углу окна, правый – от цента по оси x , вверху по оси y .
surf_left = pygame.Surface((rect_left.width, rect_left.height)) surf_left.fill(WHITE) surf_right = pygame.Surface((rect_right.width, rect_right.height))
При создании экземпляров Surface мы указываем такую же ширину и высоту как у соответствующих им прямоугольников.
sc.blit(surf_left, rect_left) sc.blit(surf_right, rect_right)
Левая и правая поверхности прорисовываются на главном окне. Координаты берутся из соответствующих экземпляров Rect .
rocket_left = Rocket(surf_left, BLACK) rocket_right = Rocket(surf_right, WHITE)
Создаются два экземпляра нашего самописного класса Rocket . Конструктору надо передать поверхность и цвет.
active_left = False active_right = False
Переменные определяют, какую анимацию проигрывать. Пока не будет произведено кликов, то никакую.
elif i.type == pygame.MOUSEBUTTONUP: if rect_left.collidepoint(i.pos): active_left = True active_right = False elif rect_right.collidepoint(i.pos): active_right = True active_left = False
Метод collidepoint() объекта Rect проверяет, находится ли точка, координаты которой были переданы в качестве аргумента, в пределах прямоугольника, к которому применяется метод. Здесь точкой являются координаты клика мыши. Если клик происходит в левом прямоугольнике, то в True устанавливается одна переменная, если в правом – то другая.
if active_left: surf_left.fill(WHITE) rocket_left.fly() sc.blit(surf_left, rect_left) pygame.display.update(rect_left) elif active_right: surf_right.fill(BLACK) rocket_right.fly() sc.blit(surf_right, rect_right) pygame.display.update(rect_right)
В зависимости от того, какая переменная в статусе True , изменения происходят только на одной из двух дочерних поверхностей. Также как update() метод blit() вызывается на каждой итерации, иначе изменения не будут видны.
Практическая работа
Напишите программу, где в центре окна находится круг, изменяющий свой цвет на каждой итерации цикла. Если нажимается клавиша 1, продолжать изменяться должен цвет только верхней половины круга. Если 2 – только нижней. Нажатие цифры 3 должно возобновлять обновление всей поверхности.
Курс с примерами решений практических работ:
pdf-версияX Скрыть Наверх
Pygame. Введение в разработку игр на Python
PyGame. Введение
Довелось мне как-то пообщаться с этой библиотекой, чем и хотелось бы поделиться с вами, и себе зарубочку оставить, дабы не забывать:) В этом небольшом, надеюсь, посте, я на наглядном примере, опуская некоторые самые-самые теоретические основы (которые изложены в документации), покажу базовые принципы работы с библиотекой.
Задача.
Создать «игровое» пространство, в котором, при помощи клавиш-стрелок, можно будет перемещать объект.
Теория.
Прежде чем выкладывать листинги, остановлюсь на используемых методах из модулей библиотеки, описание которых взято из оф. документации.
Модуль image
1. pygame.image.load (filename): return Surface
Как можно догадаться, функция загружает некоторое изображение, и возвращеает в виде поверхности, типа, с которым при помощи функций pygame уже можно выполнять какие-либо операции (трансформировать, перемащать, удалять и пр.)Модуль Surface
2. Surface.blit (source, dest, area=None, special_flags = 0)
Отрисовывает заданную поверхность (source) поверх базовой (Surface), где dest — кортеж (x, y), кординат отрисвоки, area — (width, height) — размеры source поверхности. На счет флагов, если честно пока не разбирался))
3. Surface.get_rect ()
Возвращет кортеж вида (x, y, width, height), где x, y — кординаты левого верхнего угла поверхности (Surface), width, height — соответственно ее размеры.Модуль event
Он позволяет взаимодействовать с событиями и запросами. Иными словами, любое событие в pygame, нажатие клавиши например, помещается в список, состоящий из Event objects. Все эти «событийные объекты» имеют тип, получить доступ к которому можно путем Event.type.
4. pygame.event.get ()
Метод get () позволяет получить список событий.Модуль Rect
Модуль для работы с кортежами типа rect.
5. Rect.move (X, Y)
Возвращает новый rect, в котором координаты смещены, относительно исходных, на заданные X, Y, в качестве которых может быть положительное или отрицательное целое число.Практика.
Взяв на вооружение вышесказанное, получаем:
- # -*- coding: cp1251 -*-
- # Пример реализации движения при помощи pygame.
- from pygame import *
- import sys
- # Инициализируем загруженную библиотеку.
- init ( )
- # Создаем окно разрешением 640х480
- screen = display. set_mode ( ( 640 , 480 ) )
- # Устанавливаем название окна
- display. set_caption ( ‘example’ )
- # Загружаем фоновый рисунок, в формате:
- # jpg, png, gif(без анимации), bmp, pcx, tga(без сжатия), tif.
- background = image. load ( ‘background.bmp’ )
- # Отрисовываем рисунок в нашем окне
- screen. blit ( background, ( 0 , 0 ) )
- # Создаем игровой объект
- class GameObj:
- def __init__ ( self , img, x, y, step ) :
- self . img = img # Картинка объекта
- self . x = x # x, y — коодинаты начального положения
- self . y = y
- self . step = step # Шаг, на который будет смещаться объкт
- self . pos = img. get_rect ( ) . move ( x, y )
- def _move ( self , event ) :
- if event. key == K_UP: #273 код клавиши вверх
- self . pos = self . pos . move ( 0 , — self . step )
- if event. key == K_DOWN:
- self . pos = self . pos . move ( 0 , self . step )
- if event. key == 276 :
- self . pos = self . pos . move ( — self . step , 0 )
- if event. key == 275 :
- self . pos = self . pos . move ( self . step , 0 )
- avatar = image. load ( ‘player.bmp’ )
- # Инициируем игровой объект
- x = GameObj ( avatar, 320 , 220 , 10 )
- # Рисуем картинку объекта, в его координатах
- screen. blit ( x. img , x. pos )
- # Запускаем бесконечный цикл, чтобы окно не схлопнулось после появления 🙂
- while 1 :
- for i in event. get ( ) : # Перебор в списке событий
- if i. type == QUIT: # Обрабатываем событие шечка по крестику закрытия окна
- sys . exit ( )
- if i. type == KEYDOWN:
- screen. blit ( background, x. pos , x. pos )
- x._move ( i )
- screen. blit ( x. img , x. pos )
- # Обновляем изображение в окне, чтобы изменения в нем стали видны
- display. flip ( )
Послесловие.
Собственно вот и все, коротко и сердито:) Полистав огромное колл-во игр, выложенных на оф. сайте, и обнаружив там настоящие 3д поделки — удивился и возрадовался одновременно)) Хоть я и не собираюсь покорять игродельческие вершины, но приятно, что любимый язык настолько многомерен. Если кому-то будет интересна эта тема, и у меня не пропадет желание записывать — то непременно будет продолжение).