Библиотека Pygame / Часть 1. Введение
Это первая часть серии руководств «Разработка игр с помощью Pygame». Она предназначена для программистов начального и среднего уровней, которые заинтересованы в создании игр и улучшении собственных навыков кодирования на Python.
Код в уроках был написан на Python 3.7 и Pygame 1.9.6
Что такое Pygame?
Pygame — это «игровая библиотека», набор инструментов, помогающих программистам создавать игры. К ним относятся:
- Графика и анимация
- Звук (включая музыку)
- Управление (мышь, клавиатура, геймпад и так далее)
Игровой цикл
В сердце каждой игры лежит цикл, который принято называть «игровым циклом». Он запускается снова и снова, делая все, чтобы работала игра. Каждый цикл в игре называется кадром.
В каждом кадре происходит масса вещей, но их можно разбить на три категории:
Речь идет обо всем, что происходит вне игры — тех событиях, на которые она должна реагировать. Это могут быть нажатия клавиш на клавиатуре, клики мышью и так далее.
Изменение всего, что должно измениться в течение одного кадра. Если персонаж в воздухе, гравитация должна потянуть его вниз. Если два объекта встречаются на большой скорости, они должны взорваться.
В этом шаге все выводится на экран: фоны, персонажи, меню. Все, что игрок должен видеть, появляется на экране в нужном месте.
Время
Еще один важный аспект игрового цикла — скорость его работы. Многие наверняка знакомы с термином FPS, который расшифровывается как Frames Per Second (или кадры в секунду). Он указывает на то, сколько раз цикл должен повториться за одну секунду. Это важно, чтобы игра не была слишком медленной или быстрой. Важно и то, чтобы игра не работала с разной скоростью на разных ПК. Если персонажу необходимо 10 секунд на то, чтобы пересечь экран, эти 10 секунд должны быть неизменными для всех компьютеров.
Создание шаблона Pygame
Теперь, зная из каких элементов состоит игра, можно переходить к процессу написания кода. Начать стоит с создания простейшей программы pygame, которая всего лишь открывает окно и запускает игровой цикл. Это отправная точка для любого проекта pygame.
В начале программы нужно импортировать необходимые библиотеки и задать базовые переменные настроек игры:
# Pygame шаблон - скелет для нового проекта Pygame import pygame import random WIDTH = 360 # ширина игрового окна HEIGHT = 480 # высота игрового окна FPS = 30 # частота кадров в секунду
Дальше необходимо открыть окно игры:
# создаем игру и окно pygame.init() pygame.mixer.init() # для звука screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("My Game") clock = pygame.time.Clock()
pygame.init() — это команда, которая запускает pygame. screen — окно программы, которое создается, когда мы задаем его размер в настройках. Дальше необходимо создать clock , чтобы убедиться, что игра работает с заданной частотой кадров.
Теперь необходимо создать игровой цикл:
# Цикл игры running = True while running: # Ввод процесса (события) # Обновление # Визуализация (сборка)
Игровой цикл — это цикл while , контролируемый переменной running . Если нужно завершить игру, необходимо всего лишь поменять значение running на False . В результате цикл завершится. Теперь можно заполнить каждый раздел базовым кодом.
Раздел рендеринга (отрисовки)
Начнем с раздела отрисовки. Персонажей пока нет, поэтому экран можно заполнить сплошным цветом. Чтобы сделать это, нужно разобраться, как компьютер обрабатывает цвета.

Экраны компьютеров сделаны из пикселей, каждый из которых содержит 3 элемента: красный, зеленый и синий. Цвет пикселя определяется тем, как горит каждый из элементов:
Каждый из трех основных цветов может иметь значение от 0 (выключен) до 255 (включен на 100%), так что для каждого элемента есть 256 вариантов.
Узнать общее количество отображаемых компьютером цветов можно, умножив:
>>> 256 * 256 * 256 16,777,216
Теперь, зная, как работают цвета, можно задать их в начале программ:
# Цвета (R, G, B) BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255)
А после этого — заполнить весь экран.
# Рендеринг screen.fill(BLACK)
Но этого недостаточно. Дисплей компьютера работает не так. Изменить пиксель — значит передать команду видеокарте, чтобы она передала соответствующую команду экрану. По компьютерным меркам это очень медленный процесс. Если нужно нарисовать на экране много всего, это займет много времени. Исправить это можно оригинальным способом, который называется — двойная буферизация. Звучит необычно, но вот что это такое.
Представьте, что у вас есть двусторонняя доска, которую можно поворачивать, показывая то одну, то вторую сторону. Одна будет дисплеем (то, что видит игрок), а вторая — оставаться скрытой, ее сможет «видеть» только компьютер. С каждым кадром рендеринг будет происходить на задней части доски. Когда отрисовка завершается, доска поворачивается и ее содержимое демонстрируется игроку.
А это значит, что процесс отрисовки происходит один раз за кадр, а не при добавлении каждого элемента.
В pygame это происходит автоматически. Нужно всего лишь сказать доске, чтобы она перевернулась, когда отрисовка завершена. Эта команда называется flip() :
# Рендеринг screen.fill(BLACK) # после отрисовки всего, переворачиваем экран pygame.display.flip()
Главное — сделать так, чтобы функция flip() была в конце. Если попытаться отрисовать что-то после поворота, это содержимое не отобразится на экране.
Раздел ввода (событий)
Игры еще нет, поэтому пока сложно сказать, какие кнопки или другие элементы управления понадобятся. Но нужно настроить одно важное событие. Если попытаться запустить программу сейчас, то станет понятно, что нет возможности закрыть окно. Нажать на крестик в верхнем углу недостаточно. Это тоже событие, и необходимо сообщить программе, чтобы она считала его и, соответственно, закрыла игру.
События происходят постоянно. Что, если игрок нажимает кнопку прыжка во время отрисовки? Это нельзя игнорировать, иначе игрок будет разочарован. Для этого pygame сохраняет все события, произошедшие с момента последнего кадра. Даже если игрок будет лупить по кнопкам, вы не пропустите ни одну из них. Создается список, и с помощью цикла for можно пройтись по всем из них.
for event in pygame.event.get(): # проверить закрытие окна if event.type == pygame.QUIT: running = False
В pygame много событий, на которые он способен реагировать. pygame.QUIT — событие, которое стартует после нажатия крестика и передает значение False переменной running , в результате чего игровой цикл заканчивается.
Контроль FPS
Пока что нечего поместить в раздел Update (обновление), но нужно убедиться, что настройка FPS контролирует скорость игры. Это можно сделать следующим образом:
while running: # держим цикл на правильной скорости clock.tick(FPS)
Команда tick() просит pygame определить, сколько занимает цикл, а затем сделать паузу, чтобы цикл (целый кадр) длился нужно время. Если задать значение FPS 30, это значит, что длина одного кадра — 1/30, то есть 0,03 секунды. Если цикл кода (обновление, рендеринг и прочее) занимает 0,01 секунды, тогда pygame сделает паузу на 0,02 секунды.
Итог
Наконец, нужно убедиться, что когда игровой цикл завершается, окно игры закрывается. Для этого нужно поместить функцию pygame.quit() в конце кода. Финальный шаблон pygame будет выглядеть вот так:
# Pygame шаблон - скелет для нового проекта Pygame import pygame import random WIDTH = 360 HEIGHT = 480 FPS = 30 # Задаем цвета WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # Создаем игру и окно pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("My Game") clock = pygame.time.Clock() # Цикл игры running = True while running: # Держим цикл на правильной скорости clock.tick(FPS) # Ввод процесса (события) for event in pygame.event.get(): # check for closing window if event.type == pygame.QUIT: running = False # Обновление # Рендеринг screen.fill(BLACK) # После отрисовки всего, переворачиваем экран pygame.display.flip() pygame.quit()
Ура! У вас есть рабочий шаблон Pygame. Сохраните его в файле с понятным названием, например, pygame_template.py , чтобы можно было использовать его каждый раз при создании нового проекта pygame.
В следующем руководстве этот шаблон будет использован как отправная точка для изучения процесса отрисовки объектов на экране и их движения.
Создание игр на Python 3 и Pygame: Часть 1
Многие разработчики приходят в разработку ПО, потому что хотят создавать игры. Не все могут стать профессиональными разработчиками игр, но любой может создавать собственные игры из интереса (а может быть, и с выгодой). В этом туториале, состоящем из пяти частей, я расскажу вам, как создавать двухмерные однопользовательские игры с помощью Python 3 и замечательного фреймворка PyGame.
Мы создадим версию классической игры Breakout. Освоив этот туториал, вы будете чётко понимать, что необходимо для создания игры, познакомитесь с возможностями Pygame и напишете собственный пример игры.
Мы реализуем следующие функции и возможности:
- простые стандартные GameObject и TextObject
- простой стандартный Game object
- простая стандартная кнопка
- файл конфигурации
- обработка событий клавиатуры и мыши
- кирпичи, ракетка и мяч
- управление движением ракетки
- обработка коллизий мяча с объектами игры
- фоновое изображение
- звуковые эффекты
- расширяемая система спецэффектов

Готовый исходный код выложен здесь.
Краткое введение в программирование игр
Главное в играх — перемещение пикселей на экране и издаваемый шум. Почти во всех видеоиграх есть эти элементы. В этой статье мы не будем рассматривать клиент-серверные и многопользовательские игры, для которых требуется много сетевого программирования.
Основной цикл
Основной цикл (main loop) игры выполняется и обновляет экран через фиксированные интервалы времени. Они называются частотой кадров и определяют плавность перемещения. Обычно игры обновляют экран 30-60 раз в секунду. Если частота будет меньше, то покажется, что объекты на экране дёргаются.
Внутри основного цикла есть три основных операции: обработка событий, обновление состояния игры и отрисовка текущего состояния на экране.
Обработка событий
События в игре состоят из всего, что происходит за пределами управления кода игры, но относится к выполнению игры. Например, если в Breakout игрок нажимает клавишу «стрелка влево», то игре нужно переместить ракетку влево. Стандартными событиями являются нажатия (и отжатия) клавиш, движение мыши, нажатия кнопок мыши (особенно в меню) и события таймера (например, действие спецэффекта может длиться 10 секунд).
Обновление состояния
Сердце любой игры — это её состояние: всё то, что она отслеживает и отрисовывает на экране. В случае Breakout к состоянию относятся положение всех кирпичей, позиция и скорость мяча, положение ракетки, а также жизни и очки.
Существует также вспомогательное состояние, позволяющее управлять игрой:
- Отображается ли сейчас меню?
- Закончена ли игра?
- Победил ли игрок?
Отрисовка
Игре нужно отображать своё состояние на экране, в том числе отрисовывать геометрические фигуры, изображения и текст.
Игровая физика
В большинстве игр симулируется физическое окружение. В Breakout мяч отскакивает от объектов и имеет очень приблизительную систему физики твёрдого тела (если это можно так назвать).
В более сложных играх могут использоваться более изощрённые и реалистичные физические системы (особенно в 3D-играх). Стоит также отметить, что в некоторых играх, например, в карточных, физики почти нет, и это совершенно нормально.
ИИ (искусственный интеллект)
Во многих играх мы сражаемся с компьютерными противниками, или в них есть враги, пытающиеся нас убить. Часто они ведут себя в игровом мире так, как будто обладают разумом.
Например, враги преследуют игрока и знают о его местоположении. В Breakout нет никакого ИИ. Игрок сражается с холодными и твёрдыми кирпичами. Однако ИИ в играх часто очень прост и всего лишь следует простым (или сложным) правилам, обеспечивающим псевдоразумные результаты.
Воспроизведение звука
Воспроизведение звука — ещё один важный аспект игр. В общем случае существует два типа звука: фоновая музыка и звуковые эффекты. В Breakout я реализую только звуковые эффекты, которые воспроизводятся при различных событиях.
Фоновая музыка — это просто музыка, постоянно играющая на фоне. В некоторых играх она не используется, а в некоторых меняется на каждом уровне.
Жизни, очки и уровни
В большинстве игр игрок имеет определённое количество жизней, и когда они заканчиваются, игра завершается. Также в играх часто присутствуют очки, позволяющие понять, насколько хорошо мы играем, и дающие мотивацию к самосовершенствованию или просто хвастаться друзьям своими рекордами. Во многих играх есть уровни, которые или совершенно отличаются, или постепенно увеличивают сложность.
Знакомство с Pygame
Прежде чем приступить к реализации игры, давайте немного узнаем о Pygame, который возьмёт на себя большую часть работы.
Что такое Pygame?
Pygame — это фреймворк языка Python для программирования игр. Он создан поверх SDL и обладает всем необходимым:
- зрелостью
- хорошим сообществом
- открытым исходным кодом
- кроссплатформенностью
- качественной документацией
- множеством примеров игр
- простотой изучения
Установка Pygame
Введите pip install pygame , чтобы установить фреймворк. Если вам нужно что-то ещё, то следуйте инструкциям из раздела Getting Started в Wiki проекта. Если у вас, как и у меня, macOS Sierra, то могут возникнуть проблемы. Мне удалось установить Pygame без сложностей, и код работает отлично, но окно игры никогда не появляется.
Это станет серьёзным препятствием при запуске игры. В конце концов мне пришлось запускать её в Windows внутри VirtualBox VM. Надеюсь, ко времени прочтения этой статьи проблема будет решена.
Архитектура игры
Играм нужно управлять кучей информации и выполнять почти одинаковые операции со множеством объектов. Breakout — это небольшая игра, однако попытка управлять всем в одном файле может оказаться слишком утомительной. Поэтому я решил создать файловую структуру и архитектуру, которая подойдёт и для гораздо более крупных игр.
Структура папок и файлов
├── Pipfile ├── Pipfile.lock ├── README.md ├── ball.py ├── breakout.py ├── brick.py ├── button.py ├── colors.py ├── config.py ├── game.py ├── game_object.py ├── images │ └── background.jpg ├── paddle.py ├── sound_effects │ ├── brick_hit.wav │ ├── effect_done.wav │ ├── level_complete.wav │ └── paddle_hit.wav └── text_object.py
Pipfile и Pipfile.lock — это современный способ управления зависимостями в Python. Папка images содержит изображения, используемые игрой (в нашей версии будет только фоновое изображение), а в папке sound_effects directory лежат короткие звуковые клипы, используемые (как можно догадаться) в качестве звуковых эффектов.
Файлы ball.py, paddle.py и brick.py содержат код, относящийся к каждому из этих объектов Breakout. Подробнее я рассмотрю их в следующих частях туториала. Файл text_object.py содержит код отображения текста на экране, а в файле background.py содержится игровая логика Breakout.
Однако существует несколько модулей, создающих произвольный «скелет» общего назначения. Определённые в них классы можно будет использовать в других играх на основе Pygame.
Класс GameObject
GameObject представляет собой визуальный объект, знающий о том, как себя рендерить, сохранять свои границы и перемещаться. В Pygame есть и класс Sprite, исполняющий похожую роль, но в этом туториале я хочу показать вам, как всё работает на низком уровне, а не полагаться слишком активно на готовую магию. Вот как выглядит класс GameObject:
from pygame.rect import Rect class GameObject: def __init__(self, x, y, w, h, speed=(0,0)): self.bounds = Rect(x, y, w, h) self.speed = speed @property def left(self): return self.bounds.left @property def right(self): return self.bounds.right @property def top(self): return self.bounds.top @property def bottom(self): return self.bounds.bottom @property def width(self): return self.bounds.width @property def height(self): return self.bounds.height @property def center(self): return self.bounds.center @property def centerx(self): return self.bounds.centerx @property def centery(self): return self.bounds.centery def draw(self, surface): pass def move(self, dx, dy): self.bounds = self.bounds.move(dx, dy) def update(self): if self.speed == [0, 0]: return self.move(*self.speed)
GameObject предназначен для того, чтобы быть базовым классом для других объектов. Он непосредственно раскрывает множество свойств его прямоугольника self.bounds, а в своём методе update() он перемещает объект в соответствии с его текущей скоростью. Он ничего не делает в своём методе draw() , который должен быть переопределён подклассами.
Класс Game
Класс Game — это ядро игры. Он выполняется в основном цикле. В нём есть множество полезных возможностей. Давайте разберём его метод за методом.
Метод __init__() инициализирует сам Pygame, систему шрифтов и звуковой микшер. Три разных вызова нужны, так как не во всякой игре на Pygame используются все компоненты, поэтому можно контролировать подсистемы, которые мы используем, и инициализировать только нужные с соответствующими параметрами. Метод создаёт фоновое изображение, основную поверхность (на которой всё отрисовывается) и игровой таймер с правильной частотой кадров.
Элемент self.objects хранит все игровые объекты, которые должны рендериться и обновляться. Различные обработчики управляют списками функций-обработчиков, которые должны выполняться при определённых событиях.
import pygame import sys from collections import defaultdict class Game: def __init__(self, caption, width, height, back_image_filename, frame_rate): self.background_image = \ pygame.image.load(back_image_filename) self.frame_rate = frame_rate self.game_over = False self.objects = [] pygame.mixer.pre_init(44100, 16, 2, 4096) pygame.init() pygame.font.init() self.surface = pygame.display.set_mode((width, height)) pygame.display.set_caption(caption) self.clock = pygame.time.Clock() self.keydown_handlers = defaultdict(list) self.keyup_handlers = defaultdict(list) self.mouse_handlers = []
Методы update() и draw() очень просты. Они обходят все управляемые игровые объекты и вызывают соответствующие им методы. Если два объекта накладываются друг на друга на экране, то порядок списка объектов определяет, какой из них будет рендериться первым, а остальные будут частично или полностью его перекрывать.
def update(self): for o in self.objects: o.update() def draw(self): for o in self.objects: o.draw(self.surface)
Метод handle_events() слушает события, генерируемые Pygame, такие как события клавиш и мыши. Для каждого события он вызывает все функции-обработчики, которые должны обрабатывать события соответствующих типов.
def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: for handler in self.keydown_handlers[event.key]: handler(event.key) elif event.type == pygame.KEYUP: for handler in self.keydown_handlers[event.key]: handler(event.key) elif event.type in (pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP, pygame.MOUSEMOTION): for handler in self.mouse_handlers: handler(event.type, event.pos)
Наконец, метод run() выполняет основной цикл. Он выполняется до тех пор, пока элемент game_over не принимает значение True. В каждой итерации он рендерит фоновое изображение и вызывает по порядку методы handle_events() , update() и draw() .
Затем он обновляет экран, то есть записывает на физический дисплей всё содержимое, которое было отрендерено на текущей итерации. И последнее, но не менее важное — он вызывает метод clock.tick() для управления тем, когда будет вызвана следующая итерация.
def run(self): while not self.game_over: self.surface.blit(self.background_image, (0, 0)) self.handle_events() self.update() self.draw() pygame.display.update() self.clock.tick(self.frame_rate)
Заключение
В этой части мы изучили основы программирования игр и все компоненты, участвующие в создании игр. Также мы рассмотрели сам Pygame и узнали, как его установить. Наконец, мы погрузились в архитектуру игры и изучили структуру папок, классы GameObject и Game.
Во второй части мы рассмотрим класс TextObject , используемый для рендеринга текста на экране. Мы создадим основное окно, в том числе и фоновое изображение, а затем узнаем, как отрисовывать объекты (мяч и ракетку).
Как создать игру на Python с использованием Pygame

Python — один из самых популярных языков программирования, который благодаря своей простоте и универсальности стал основой для множества проектов. Сегодня мы рассмотрим создание игры на Python с использованием библиотеки Pygame.
Что такое Pygame?
Pygame — это набор модулей, предназначенных для написания видеоигр на Python. Он предоставляет возможности для работы с графикой, звуком и управлением, что делает его отличным инструментом для создания простых и средних игр. ️
Установка Pygame
Для начала установим библиотеку Pygame. Откройте терминал и выполните следующую команду:
pip install pygame
Теперь Pygame установлен, и мы можем начать создавать нашу игру!
Создание окна игры
Сначала импортируем библиотеку Pygame и инициализируем ее:
import pygame pygame.init()
Затем создадим окно игры с заданными размерами:
screen = pygame.display.set_mode((800, 600))
Теперь наш игровой экран готов, и мы можем перейти к созданию объектов и управлению игровым процессом.
Python-разработчик: новая работа через 9 месяцев
Получится, даже если у вас нет опыта в IT

Создание объектов и управление игровым процессом
Рассмотрим пример создания простой игры, в которой управляемый игроком квадрат должен ловить движущиеся по экрану круги.
- Создадим классы для игрока и кругов:
class Player(pygame.sprite.Sprite): # Код для создания и управления игроком class Circle(pygame.sprite.Sprite): # Код для создания движущихся кругов
- Реализуем в классах методы для отрисовки и обновления состояний объектов:
class Player(pygame.sprite.Sprite): def __init__(self, x, y): # Код для создания игрока def update(self): # Код для обновления состояния игрока class Circle(pygame.sprite.Sprite): def __init__(self, x, y, speed): # Код для создания круга def update(self): # Код для обновления состояния круга
- Создадим группы спрайтов для удобства управления и отрисовки объектов:
player_group = pygame.sprite.Group() circle_group = pygame.sprite.Group()
- Реализуем основной игровой цикл, в котором будут происходить обновление состояний объектов и их отрисовка на экране:
running = True while running: # Обработка событий # Обновление состояний объектов # Отрисовка объектов на экране
После того, как ваша игра будет готова, не забудьте освободить ресурсы и закрыть окно Pygame:
pygame.quit()
Теперь вы знаете основы создания игр на Python с использованием библиотеки Pygame! Этот навык может стать отличным началом для карьеры в сфере Python-разработки. Если вы хотите продолжить развиваться в этом направлении, рекомендую обратиться к хорошей онлайн школе, которая учит специалистов в сфере «Python-разработка».
Как писать игры на Python с Pygame
Этот туториал поможет вам сделать заготовку для простой игры, в которой вы будете перемещать своего персонажа, чтобы избежать столкновения с препятствиями. Вы будете использовать Pygame — набор модулей Python, предназначенных для написания видеоигр. Pygame добавляет функциональность поверх превосходной библиотеки SDL. В последней версии используется Pygame SDL2 .
Установка библиотеки
Pygame состоит из нескольких модулей с функциями для рисования графики, воспроизведения звуков, обработки ввода с помощью мыши и других вещей, которые вам понадобятся при разработке своей первой игры на Python 3 .
Для начала работы с библиотекой необходимо добавить ее в локальную среду разработки. На Python Pygame-установка выполняется через pip:
python -m pip install -U pygame --user
Чтобы убедиться в том, что библиотека работает, запустите встроенный пример игры:
python -m pygame.examples.aliens
Должна запуститься игра, в которой нужно уничтожать летающие тарелки инопланетян.
Есть и другие способы установки для разных операционных систем, компиляция библиотеки из исходников. Смотрите их в документации Pygame .
Игровой цикл
Игровой цикл — это место, где все игровые события происходят, обновляются и отображаются на экране. Как только первоначальная настройка и инициализация переменных завершены, начинается игровой цикл, в котором программа продолжает повторяться снова и снова, пока не произойдет событие типа QUIT.
Ниже приведен тип цикла Game, который мы будем использовать в нашей программе Pygame.
while True:
# Code
pygame.display.update()
Изменения в игре не вступают в силу до тех пор, пока не будет выполнена команда display.update() . Поскольку в играх всё безостановочно меняется, функция обновления находится в игровом цикле и тоже выполняется постоянно.
Выход из игрового цикла
У каждого игрового цикла должна быть конечная точка или действие, которое запускает конечную точку — например, нажатие кнопки выхода.
while True:
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Мы вызываем pygame.quit() и sys.exit() , чтобы закрыть окно Pygame и завершить скрипт Python соответственно. Простое использование sys.exit() может привести к зависанию IDE.
Игровые события
Событие происходит, когда пользователь выполняет определенное действие. Например, щелкает мышью или нажимает кнопку на клавиатуре. Pygame записывает каждое происходящее событие.
Вы можете узнать, какие события произошли, вызвав функцию pygame.event.get() . Она возвращает список объектов pygame.event.Event . Для краткости будем называть это объектами событий.
Одним из многих атрибутов (или свойств), которыми обладают объекты событий, является тип — type . Атрибут type сообщает, какое событие представляет объект.
В примере выше использован event.type == QUIT . Он помогает определить, должна игра быть закрыта или нет. Пока пользователь не закроет игру (говоря языком Pygame, не вызовет событие ‘QUIT’), она будет работать в бесконечном цикле.
Игровой экран
Для игры нужно создать окно фиксированного размера, внутри которого будут происходить все события. Ширина и высота этого окна в пикселях передаются в функцию pygame set mode в виде кортежа.
DISPLAYSURF = pygame.display.set_mode((300,300))
Пиксель — наименьшая возможная область на экране. Не существует половины пикселя или четверти пикселя. Поэтому ширина и высота должны быть целыми числами.
Кадровая частота
Если не задать ограничение на частоту кадров, компьютер будет выполнять игровой цикл столько раз, сколько может в течение секунды. Чтобы ограничить его, используйте метод ‘tick(fps)’, где fps — целое число. Метод ‘tick(fps)’ принадлежит классу ‘ pygame.time.Clock ’ и должен использоваться с объектом этого класса.
FPS = pygame.time.Clock()
FPS.tick(60)
Это может варьироваться от игры к игре, в зависимости от того, как она была разработана, но вы должны стремиться к значению от 30 до 60. Имейте в виду, что, если вы создаете довольно сложную и тяжелую игру, компьютер может не справиться с ней на более высоких кадрах.
Цвета
Pygame использует систему цветов RGB (Red, Green, Blue). Значения для каждого цвета находятся в диапазоне от 0 до 255, всего 256 значений. Сочетание этих трех цветов используется для создания всех цветов, которые вы видите на компьютерах или на любом устройстве с экраном.
Чтобы использовать цвета в Pygame, создают объекты Color, используя значения RGB. Значения RGB должны быть в формате кортежа с тремя значениями для каждого основного цвета.
BLACK = pygame.Color(0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
GREY = pygame.Color(128, 128, 128)
RED = pygame.Color(255, 0, 0)
В работе с цветами есть одна особенность. Например, если вы нарисуете квадрат и зададите ему зеленый цвет, то по умолчанию зелеными станут только границы. Для полной заливки объектов используйте метод ‘fill’. Это сделает квадрат полностью зеленым.
Создание игры
Теперь пришло время заняться самым интересным — разработать первую игру.
Вот так выглядит полный код проекта, который получится у вас после прохождения этого туториала.
# Импортируем библиотеки
import pygame, sys
from pygame.locals import *
import random
# Инициализируем Pygame
pygame.init()
# Ограничиваем количество кадров в секунду
FPS = 60
FramePerSec = pygame.time.Clock()
# Задаем цвет
WHITE = (255, 255, 255)
# Задаем размеры игрового экрана
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
# Отрисовываем экран и заливаем его белым цветом
DISPLAYSURF = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT)))
DISPLAYSURF.fill(WHITE)
pygame.display.set_caption("Game")
# Определяем класс игрока
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("Player.png")
self.rect = self.image.get_rect()
self.rect.center = (160, 520)
def update(self):
pressed_keys = pygame.key.get_pressed()
if self.rect.left > 0:
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if self.rect.right < SCREEN_WIDTH:
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5, 0)
def draw(self, surface):
surface.blit(self.image, self.rect)
# Определяем класс врага
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("Enemy.png")
self.rect = self.image.get_rect()
self.rect.center=(random.randint(40,SCREEN_WIDTH-40),0)
def move(self):
self.rect.move_ip(0,10)
if (self.rect.bottom > 600):
self.rect.top = 0
self.rect.center = (random.randint(30, 370), 0)
def draw(self, surface):
surface.blit(self.image, self.rect)
# Создаем персонажей
P1 = Player()
E1 = Enemy()
# Определяем игровой цикл
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
P1.update()
E1.move()
DISPLAYSURF.fill(WHITE)
P1.draw(DISPLAYSURF)
E1.draw(DISPLAYSURF)
pygame.display.update()
FramePerSec.tick(FPS)
Теперь давайте разбирать, какие Pygame Python-команды здесь используются.
Инициализация игры
Создание игры на Python с Pygame начинается с импорта библиотеки. Откройте файл в любой IDE или редакторе кода и добавьте две строки:
import pygame
from pygame.locals import *
Первой строкой вы импортировали модуль Pygame Python 3. Второй строкой вы импортировали все переменные из pygame.locals.
Можно обойтись без второго импорта. Но он заметно сокращает количество кода. Например, событие выхода из игры без импорта переменных из pygame.locals придется записывать так: ‘pygame.locals.QUIT’. С импортом же синтаксис гораздо короче — для добавления события достаточно написать ‘QUIT’.
Чтобы использовать случайные значения, импортируйте библиотеку random. Без нее игра будет предсказуемой:
import random
В начале файла должна быть ещё одна важная строка:
pygame.init()
Эта строка обязательна при использовании библиотеки Pygame. Ее нужно добавить перед любой другой функцией библиотеки, иначе возникнут проблемы с инициализацией. Поэтому вы добавляете init() в начале файла, чтобы исключить появление ошибок.
Определение персонажей
В проекте используется объектно-ориентированный подход. Это позволяет создавать классы, которые становятся основой для разных персонажей. Например, у вас будет один класс врагов (препятствий в игре), а по мере прохождения раундов они будут видоизменяться и получать дополнительные способности.
Сначала определим класс игрока:
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("Player.png")
self.rect = self.image.get_rect()
self.rect.center = (160, 520)
Функция image.load() принимает на вход файл изображения. Чтобы определить границы спрайта игрока, достаточно вызвать функцию get_rect() . Она автоматически создаст прямоугольник того же размера, что и изображение. Это будет полезно в дальнейшей разработке, когда вы, например, будете реализовывать логику столкновения объектов. Последняя строка self.rect.center определяет начальную позицию персонажа на игровом поле.
def update(self):
pressed_keys = pygame.key.get_pressed()
if self.rect.left > 0:
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if self.rect.left > 0:
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5, 0)
Метод update управляет движением игрока. При его вызове выполняется проверка, нажаты ли клавиши.
В этом проекте нас интересует только движение влево и вправо, которое позволяет избегать препятствий. Если игрок нажимает на левую стрелку, выполняется перемещение его персонажа налево. Аналогично реализована логика движения направо.
Метод move_ip() принимает два параметра. Первый параметр — это расстояние в пикселях, на которое необходимо переместить объект по горизонтали. Второй параметр — расстояние, на которое необходимо переместить объект по вертикали.
Операторы if self.rect.left > 0 и if self.rect.left > 0 гарантируют, что игрок не выйдет за пределы игрового поля.
def draw(self, surface):
surface.blit(self.image, self.rect)
Функция blit() принимает параметры. Первый — объект для отрисовки, а второй — его спрайт. Поскольку вы используете изображение, то передаете self.image в качестве объекта для отрисовки.
Класс врага устроен очень похоже. Единственное отличие — использование генератора случайных чисел:
self.rect.center=(random.randint(40,SCREEN_WIDTH-40),0)
Это нужно для того, чтобы препятствие каждый раз появлялось в новом месте. Иначе игра будет предсказуемой.
Игровой цикл
И самая важная часть — игровой цикл:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
P1.update()
E1.move()
DISPLAYSURF.fill(WHITE)
P1.draw(DISPLAYSURF)
E1.draw(DISPLAYSURF)
pygame.display.update()
FramePerSec.tick(FPS)
Цикл выполняется бесконечно, пока пользователь не закончит игру. Это самая простая реализация. На практике к завершению игры могут приводить разные события — например, исчерпание лимита жизней персонажа.
Сначала вызываются функции update для классов Enemy и Player. Далее цикл обновляет экран с помощью DISPLAY.fill(WHITE) . Наконец, вызывается функция draw для отрисовки объектов на экране.
Наконец, команда pygame.display.update() обновляет экран, выводя все изменения, которые произошли до этого момента. Функция tick() гарантирует, что количество кадров в секунду при этом не превышает установленного ранее значения FPS.
Заключение
Игра готова. Она пока не настолько хороша, чтобы арендовать сервер для хостинга на timeweb.cloud и ждать наплыва игроков. Но это ваша первая игра на Питон — и теперь вы знаете, как сделать ее лучше. Например, как добавить персонажу движение вверх и вниз или изменить логику появления препятствий.
Возможностей для совершенствования проекта очень много. Например, можно сделать двумерную игру трехмерной, используя Pygame raycast. Да, на Pygame не получится разработать клона Cyberpunk 2077, но свою версию Wolfenstein 3D сделать реально.
Есть большое количество туториалов и гайдов по использованию Pygame на русском языке . Они помогут изучить не только особенности библиотеки, но и некоторые универсальные концепции геймдева. Если позже вы переключитесь на более продвинутый игровой движок, многие из этих концепций останутся актуальными.