Python – интерпретируемый язык, и по этой причине он не отличается высокой производительностью, которая необходима для сложных игр с гиперреалистичной графикой. Тем не менее есть несколько способов оптимизации, которые значительно ускоряют выполнение Python-кода, что позволяет писать на Питоне вполне приличные игры. Оптимизацию необязательно делать самостоятельно – в значительной степени эту задачу берут на себя специальные фреймворки и библиотеки. Фреймворков и библиотек для разработки игр на основе Python довольно много, вот самые популярные:
- Pygame
- PyKyra
- Pyglet
- Panda3D
- Kivy
- PyopenGL
Мы остановимся на самой популярной библиотеке, Pygame – она отлично подходит для начинающих разработчиков, и к тому же часто используется для быстрого прототипирования игр. На официальном сайте Pygame есть каталог игр, созданных с помощью библиотеки. Еще примеры игр на Pygame можно посмотреть здесь.
Pygame не входит в стандартную поставку Python, для установки библиотеки выполните:
pip install pygame
Все возможности библиотеки Pygame нереально рассмотреть в одной статье, поэтому здесь мы затронем только самые базовые концепции – рисование, движение объектов, покадровую анимацию, обработку событий, обновление счетчика, обнаружение столкновения.
Окно и главный цикл приложения
Создание любого приложения на базе Pygame начинается с импорта и инициализации библиотеки. Затем нужно определить параметры окна, и по желанию – задать цвет (или изображение) фона:
import pygame
# инициализируем библиотеку Pygame
pygame.init()
# определяем размеры окна
window_size = (300, 300)
# задаем название окна
pygame.display.set_caption("Синий фон")
# создаем окно
screen = pygame.display.set_mode(window_size)
# задаем цвет фона
background_color = (0, 0, 255) # синий
# заполняем фон заданным цветом
screen.fill(background_color)
# обновляем экран для отображения изменений
pygame.display.flip()
# показываем окно, пока пользователь не нажмет кнопку "Закрыть"
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

Цикл while True
играет роль главного цикла программы – в нем происходит отслеживание событий
приложения и действий пользователя. Функция pygame.quit() завершает работу
приложения, и ее можно назвать противоположностью функции pygame.init(). Для
завершения Python-процесса
используется exit(), с
той же целью можно использовать sys.exit(), но ее нужно
импортировать в начале программы: import sys
.
В качестве фона можно использовать изображение:
import pygame
pygame.init()
window_size = (400, 400)
screen = pygame.display.set_mode(window_size)
pygame.display.set_caption("Peter the Piglet")
# загружаем изображение
background_image = pygame.image.load("background.png")
# подгоняем масштаб под размер окна
background_image = pygame.transform.scale(background_image, window_size)
# накладываем изображение на поверхность
screen.blit(background_image, (0, 0))
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

Обработку событий (нажатий клавиш и кликов) в Pygame реализовать очень просто – благодаря встроенным функциям. Приведенный ниже код изменяет цвет фона после клика по кнопке. Обратите внимание, что в Pygame можно задавать цвет несколькими способами:
import pygame
pygame.init()
pygame.display.set_caption('Измени цвет фона')
window_surface = pygame.display.set_mode((300, 300))
background = pygame.Surface((300, 300))
background.fill(pygame.Color('#000000'))
color_list = [
pygame.Color('#FF0000'), # красный
pygame.Color('#00FF00'), # зеленый
pygame.Color('#0000FF'), # синий
pygame.Color('#FFFF00'), # желтый
pygame.Color('#00FFFF'), # бирюзовый
pygame.Color('#FF00FF'), # пурпурный
pygame.Color('#FFFFFF') # белый
]
current_color_index = 0
button_font = pygame.font.SysFont('Verdana', 15) # используем шрифт Verdana
button_text_color = pygame.Color("black")
button_color = pygame.Color("gray")
button_rect = pygame.Rect(100, 115, 100, 50)
button_text = button_font.render('Нажми!', True, button_text_color)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if button_rect.collidepoint(event.pos):
current_color_index = (current_color_index + 1) % len(color_list)
background.fill(color_list[current_color_index])
window_surface.blit(background, (0, 0))
pygame.draw.rect(window_surface, button_color, button_rect)
button_rect_center = button_text.get_rect(center=button_rect.center)
window_surface.blit(button_text, button_rect_center)
pygame.display.update()

Как очевидно из приведенного выше примера, основной цикл Pygame приложения состоит из трех повторяющихся действий:
- Обработка событий (нажатий клавиш или кнопок).
- Обновление состояния.
- Отрисовка состояния на экране.
GUI для PyGame
Pygame позволяет легко и быстро интегрировать в проект многие нужные вещи – шрифты, звук, обработку событий, – однако не имеет встроенных виджетов для создания кнопок, лейблов, индикаторов выполнения и других подобных элементов интерфейса. Эту проблему разработчик должен решать либо самостоятельно (нарисовать прямоугольник, назначить ему функцию кнопки), либо с помощью дополнительных GUI-библиотек. Таких библиотек несколько, к самым популярным относятся:
Вот простой пример использования Pygame GUI – зеленые нули и единицы падают вниз в стиле «Матрицы»:
import pygame
import pygame_gui
import random
window_size = (800, 600)
window = pygame.display.set_mode(window_size)
pygame.display.set_caption('Матрица Lite')
pygame.init()
gui_manager = pygame_gui.UIManager(window_size)
font = pygame.font.SysFont('Consolas', 20)
text_color = pygame.Color('green')
text_symbols = ['0', '1']
text_pos = [(random.randint(0, window_size[0]), 0) for i in range(50)]
text_speed = [(0, random.randint(1, 5)) for i in range(50)]
text_surface_list = []
button_size = (100, 50)
button_pos = (350, 250)
button_text = 'Матрица!'
button = pygame_gui.elements.UIButton(
relative_rect=pygame.Rect(button_pos, button_size),
text=button_text,
manager=gui_manager
)
while True:
time_delta = pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame_gui.UI_BUTTON_PRESSED:
text_surface_list = []
for i in range(50):
text_symbol = random.choice(text_symbols)
text_surface = font.render(text_symbol, True, text_color)
text_surface_list.append(text_surface)
gui_manager.process_events(event)
gui_manager.update(time_delta)
window.fill(pygame.Color('black'))
for i in range(50):
text_pos[i] = (text_pos[i][0], text_pos[i][1] + text_speed[i][1])
if text_pos[i][1] > window_size[1]:
text_pos[i] = (random.randint(0, window_size[0]), -20)
if len(text_surface_list) > i:
window.blit(text_surface_list[i], text_pos[i])
gui_manager.draw_ui(window)
pygame.display.update()

Рисование
В Pygame есть функции для простого рисования геометрических фигур – прямоугольников, окружностей, эллипсов, линий, многоугольников. Вот пример:
import pygame
import math
pygame.init()
screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Геометрические фигуры")
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
yellow = (255, 255, 0)
pink = (255, 192, 203)
# рисуем прямоугольник
rect_x = 50
rect_y = 50
rect_width = 100
rect_height = 50
pygame.draw.rect(screen, red, (rect_x, rect_y, rect_width, rect_height))
# рисуем круг
circle_x = 200
circle_y = 75
circle_radius = 30
pygame.draw.circle(screen, green, (circle_x, circle_y), circle_radius)
# рисуем треугольник
triangle_x = 350
triangle_y = 50
triangle_width = 100
triangle_height = 100
triangle_points = [(triangle_x, triangle_y), (triangle_x + triangle_width, triangle_y),
(triangle_x + triangle_width / 2, triangle_y + triangle_height)]
pygame.draw.polygon(screen, blue, triangle_points)
# рисуем пятиугольник
pent_x = 500
pent_y = 100
radius = 40
sides = 5
pent_points = []
for i in range(sides):
angle_deg = 360 * i / sides
angle_rad = math.radians(angle_deg)
x = pent_x + radius * math.sin(angle_rad)
y = pent_y - radius * math.cos(angle_rad)
pent_points.append((x, y))
pygame.draw.polygon(screen, white, pent_points)
# рисуем эллипс
ellipse_x = 100
ellipse_y = 275
ellipse_width = 150
ellipse_height = 60
pygame.draw.ellipse(screen, red, (ellipse_x, ellipse_y, ellipse_width, ellipse_height))
# горизонтальная линия
horiz_line_y = 400
pygame.draw.line(screen, blue, (50, horiz_line_y), (590, horiz_line_y), 5)
# вертикальная линия
vert_line_x = 320
pygame.draw.line(screen, green, (vert_line_x, 50), (vert_line_x, 430), 5)
# рисуем желтую звезду
yellow_star_points = [(260 - 50, 250 - 70), (310 - 50, 250 - 70), (325 - 50, 200 - 70),
(340 - 50, 250 - 70), (390 - 50, 250 - 70), (350 - 50, 290 - 70),
(365 - 50, 340 - 70), (325 - 50, 305 - 70), (285 - 50, 340 - 70),
(300 - 50, 290 - 70)]
pygame.draw.polygon(screen, yellow, yellow_star_points)
# рисуем окружность с квадратом внутри
circle2_x = 490
circle2_y = 350
circle2_radius = 80
pygame.draw.circle(screen, white, (circle2_x, circle2_y), circle2_radius)
square_side = 60
square_x = circle2_x - square_side / 2
square_y = circle2_y - square_side / 2
pygame.draw.rect(screen, pink, (square_x, square_y, square_side, square_side))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()

Анимация и обработка событий
Выше, в примере с падающими символами в «Матрице», уже был
показан принцип простейшей имитации движения, который заключается в
последовательном изменении координат объекта и обновлении экрана с
установленной частотой кадра pygame.time.Clock().tick(60)
.
Усложним задачу – сделаем простую анимацию с падающими розовыми «звездами».
Приложение будет поддерживать обработку двух событий:
- При клике мышью по экрану анимация останавливается.
- При нажатии клавиши Enter – возобновляется.
Кроме того, добавим счетчик упавших звезд. Готовый код выглядит так:
import pygame
import random
pygame.init()
screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Звезды падают вниз")
black = (0, 0, 0)
white = (255, 255, 255)
pink = (255, 192, 203)
font = pygame.font.SysFont("Verdana", 15)
star_list = []
for i in range(50):
x = random.randrange(screen_width)
y = random.randrange(-200, -50)
speed = random.randrange(1, 5)
star_list.append([x, y, speed])
score = 0
freeze = False # флаг для определения момента остановки
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN: # останавливаем падение звезд по клику
freeze = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN: # возобновляем движение вниз, если нажат Enter
freeze = False
if not freeze: # если флаг не активен,
# звезды падают вниз
for star in star_list:
star[1] += star[2]
if star[1] > screen_height:
star[0] = random.randrange(screen_width)
star[1] = random.randrange(-200, -50)
score += 1
# рисуем звезды, выводим результаты подсчета
screen.fill(black)
for star in star_list:
pygame.draw.circle(screen, pink, (star[0], star[1]), 3)
score_text = font.render("Упало звезд: " + str(score), True, white)
screen.blit(score_text, (10, 10))
pygame.display.update()
# устанавливаем частоту обновления экрана
pygame.time.Clock().tick(60)

Отлично! Вы освоили основы Pygame и создали свою первую интерактивную анимацию.
Вы умеете создавать игровое окно, рисовать объекты, анимировать их движение и обрабатывать события от мыши и клавиатуры. У вас есть все базовые инструменты.
Но анимация — это еще не игра. Чтобы превратить её в игру, нужно добавить три ключевых элемента: управляемого персонажа, взаимодействие между объектами и чёткие правила. В полной версии урока вы:
- Научитесь создавать покадровую анимацию для персонажей.
- Реализуете обнаружение столкновений — основу любой игровой механики.
- Добавите полноценное управление персонажем с клавиатуры.
- Напишете 10 полноценных мини-игр, включая «Лабиринт», «Змейку» и «Memory», чтобы создать свое первое игровое портфолио.
Над какой игрой трудитесь? Расскажите в комментариях!