Skip to content

Всё для WordPress, веб-разработки — и не только

🎮 Первая игра на Pygame: пишем на Python с нуля

🎮 Первая игра на Pygame: пишем на Python с нуля

Хотите написать свою первую игру, но не знаете, с какой стороны подойти к геймдеву? Pygame снимает этот барьер. Вы пишете на чистом Python, и сразу видите результат на экране: движущийся спрайт, реакцию на клавиши, ожившую механику. Без тяжёлых движков, без тысяч строк шаблонного кода.

Проблема большинства туториалов, они либо закапываются в теорию на 40 страниц, либо бросают вас с «допишите сами». Здесь мы пойдём по среднему пути: объясним ровно столько, чтобы вы понимали каждую строчку, и сразу соберём работающую игру, персонажа, который двигается по экрану на WASD. Весь код помещается в 60 строк.

💡 Быстрый обзор:

  • Установите Pygame через pip и создайте файл игры, это займёт пару минут
  • Разберитесь с игровым циклом: события, расчёты, отрисовка, три фазы, которые живут в бесконечном while True
  • Напишите класс игрока и оживите его: клавиши WASD двигают спрайт, экран перерисовывается 60 раз в секунду
  • Поймите систему координат и работу с цветом, два краеугольных камня, на которых держится любая 2D-графика

Что такое Pygame и почему именно он

Pygame, это библиотека для Python, которая оборачивает мультимедийную SDL (Simple DirectMedia Layer) в удобное Python-API. SDL отвечает за низкоуровневую работу с графикой, звуком и устройствами ввода, а Pygame даёт к этому доступ через привычные классы и методы. Актуальная версия, 2.6.0, библиотека активно поддерживается и работает на Windows, macOS и Linux.

Для новичка у Pygame три неоспоримых плюса. Первое, порог входа: вы используете обычный Python-код, никакого нового языка или визуального редактора. Второе, мгновенная обратная связь: написали pygame.draw.rect(...), и на экране появился прямоугольник, никакой магии. Третье, понимание фундамента: Pygame не прячет от вас игровой цикл и очередь событий, вы видите, как устроена любая игра изнутри. После Pygame пересесть на Godot или Unity будет легче, потому что вы уже знаете, что такое delta time и event polling.

Библиотека не пытается быть игровым движком. В ней нет сцены, физики или встроенного редактора уровней, и это осознанное решение. Вы контролируете каждый пиксель и каждый тик, а значит, учитесь думать как разработчик игр, а не как оператор чужого инструмента.

Установка Pygame за две минуты

Python 3.9 или новее уже стоит? Тогда открывайте терминал и выполняйте одну команду:

1pip install pygame

Для изоляции проекта лучше создать виртуальное окружение:

1python -m venv game_env
2game_env\Scripts\activate # Windows
3source game_env/bin/activate # macOS / Linux
4pip install pygame

Проверьте, что библиотека подхватилась:

1import pygame
2print(pygame.version.ver)

Если в ответ получили 2.6.0 (или новее, актуальную версию можно сверить на pygame.org), всё готово. Создайте папку проекта, положите в неё любое изображение-спрайт размером 80×80 пикселей с именем player.png и текстовый файл game.py, с него и начнём.

Как устроена игровая петля: события, расчёты, отрисовка

Сердце любой игры, главный цикл, он же main loop. Пока игра запущена, внутри бесконечного while True сменяют друг друга три фазы:

  • Обработка событий, что произошло с прошлого кадра? Нажата клавиша? Дёрнулась мышь? Окно закрыли? Pygame собирает все события в очередь, и мы проходим по ней циклом for event in pygame.event.get().

  • Расчёт логики, как изменился мир в ответ на события? Игрок нажал W, увеличиваем Y-координату. Пуля столкнулась с астероидом, помечаем оба «к удалению».

  • Отрисовка, рисуем всё, что должно быть на экране. Заливаем фон, размещаем спрайты по новым координатам, вызываем pygame.display.update(), и игрок видит кадр.

Эти три шага повторяются 60 раз в секунду, именно столько кадров (FPS) мы зададим таймеру. Иллюзия движения строится на том, что между кадрами спрайт смещается на пару пикселей, а глаз воспринимает это как непрерывную анимацию.

Пишем первый код: двигаем спрайт по экрану

Вот полный код игры. Сохраните его в game.py и положите player.png в ту же папку:

1#!/usr/bin/env python3
2
3import pygame
4import sys
5
6WIDTH, HEIGHT = 360, 480
7WHITE = (255, 255, 255)
8
9class Player(pygame.sprite.Sprite):
10
11 def __init__(self, image_path):
12 super().__init__()
13 self.image = pygame.image.load(image_path)
14 self.x = WIDTH / 2
15 self.y = HEIGHT / 2
16 self.speed = 5
17
18 def move(self, dx, dy):
19 self.x += dx
20 self.y += dy
21
22def main():
23 pygame.init()
24 screen = pygame.display.set_mode((WIDTH, HEIGHT))
25 pygame.display.set_caption("Первая игра на Pygame")
26
27 clock = pygame.time.Clock()
28 fps = 60
29
30 player = Player("player.png")
31 dx, dy = 0, 0
32
33 running = True
34 while running:
35 for event in pygame.event.get():
36 if event.type == pygame.QUIT:
37 running = False
38
39 elif event.type == pygame.KEYDOWN:
40 if event.key == pygame.K_d:
41 dx = player.speed
42 elif event.key == pygame.K_a:
43 dx = -player.speed
44 elif event.key == pygame.K_w:
45 dy = -player.speed
46 elif event.key == pygame.K_s:
47 dy = player.speed
48
49 elif event.type == pygame.KEYUP:
50 if event.key in (pygame.K_d, pygame.K_a):
51 dx = 0
52 elif event.key in (pygame.K_w, pygame.K_s):
53 dy = 0
54
55 player.move(dx, dy)
56 screen.fill(WHITE)
57 screen.blit(player.image, (player.x, player.y))
58 pygame.display.update()
59 clock.tick(fps)
60
61 pygame.quit()
62 sys.exit()
63
64if __name__ == "__main__":
65 main()
Спрайт игрока 80x80 для перемещения по экрану

Запустите python game.py, откроется окно с белым фоном и вашим спрайтом по центру. Зажмите W, A, S или D, персонаж движется. Отпустили, останавливается. Это уже настоящая игра, хоть и минимальная.

Что улучшено по сравнению с классическими туториалами: добавлен KEYUP, обработчик отпускания клавиши. Без него спрайт после первого нажатия уезжал бы за край экрана навсегда. А ещё код обёрнут в конструкцию if __name__ == "__main__", хорошая практика, которая позволяет импортировать файл как модуль без запуска игры.

Система координат и работа с цветом

В Pygame координаты отсчитываются от левого верхнего угла: (0, 0), самый верх слева. Движение вправо увеличивает X, движение вниз увеличивает Y. Это отличается от школьной системы координат, где Y растёт вверх, просто запомните и проверьте себя на первых двух запусках: нажали S, спрайт поехал вниз, нажали W, вверх.

Цвет задаётся кортежем из трёх чисел (R, G, B), каждое от 0 до 255. Белому соответствует (255, 255, 255), чёрному соответствует (0, 0, 0), красному соответствует (255, 0, 0). Метод screen.fill(WHITE) заливает весь экран выбранным цветом перед отрисовкой каждого кадра. Если этого не делать, спрайт будет оставлять за собой шлейф из предыдущих позиций.

Что происходит под капотом: построчный разбор

Класс Player наследуется от pygame.sprite.Sprite, это встроенный класс Pygame для игровых объектов. В конструкторе мы загружаем изображение через pygame.image.load() и задаём стартовую позицию по центру экрана: WIDTH / 2 и HEIGHT / 2. Метод move(dx, dy) получает смещение и прибавляет его к текущим координатам, чистая арифметика, никакой магии.

Функция main() собирает всё воедино. pygame.init() запускает внутренние подсистемы. pygame.display.set_mode() создаёт окно, а screen, это поверхность (Surface), на которой мы рисуем. pygame.time.Clock() создаёт таймер: его метод tick(fps) в конце цикла говорит Pygame «жди, пока не пройдёт 1/60 секунды с прошлого кадра», так мы фиксируем частоту кадров и не нагружаем процессор впустую.

Главный цикл while running крутится, пока флаг running не станет False. Внутри, три фазы, о которых говорили выше:

Окно игры Pygame со спрайтом персонажа на белом фоне

В цикле for event in pygame.event.get() мы опрашиваем очередь событий. pygame.QUIT, это сигнал «пользователь нажал на крестик окна»: выставляем running = False, и на следующей итерации цикл завершится. pygame.KEYDOWN срабатывает при нажатии клавиши, а KEYUP при отпускании. Для D и A меняем dx, для W и S меняем dy. Когда клавишу отпускают, обнуляем соответствующую компоненту скорости, спрайт останавливается.

screen.blit(player.image, (player.x, player.y)), метод, который «накладывает» одно изображение на другое. В нашем случае, спрайт игрока на главную поверхность экрана по текущим координатам. pygame.display.update() обновляет окно, и игрок видит готовый кадр.

Обратите внимание: player.move() вызывается до screen.fill(). Если поменять их местами, спрайт будет стираться в ту же миллисекунду, когда появляется, вы просто не увидите его на экране. Порядок операций в игровом цикле критичен.

Щёлкаете по крестику, pygame.quit() корректно выгружает подсистемы Pygame, а sys.exit() завершает процесс Python. Без pygame.quit() окно может зависнуть при закрытии, мелочь, но код должен быть аккуратным.

Короткое видео по теме

Если текстовая инструкция заходит не до конца, вот отличный видеокурс на английском, где по шагам собирают Space Invaders на Pygame. Все концепции из статьи показаны вживую:

⁉️🤔 Частые вопросы

Нужно ли знать ООП для Pygame?

Да, на базовом уровне. Классы, методы, наследование и self вам понадобятся с первого дня: игрок, враги, пули и бонусы естественно ложатся в объектную модель. Если вы прошли любой introductory-курс по Python, где объясняли class и __init__, этого достаточно. Остальное доберёте по ходу: Pygame не требует паттернов проектирования, обычного наследования от Sprite хватает для десятков прототипов. Игровой объект в Pygame, это класс, унаследованный от pygame.sprite.Sprite. В конструкторе вы загружаете спрайт через pygame.image.load(), задаёте начальные координаты и скорость. Метод update() (или свой, вроде move()) меняет позицию на каждом кадре. Главный цикл дёргает update() у всех объектов, потом отрисовывает их через screen.blit(). Никакой магии, просто вызов методов в правильном порядке 60 раз в секунду.

Тормозит ли Pygame на сложной 2D-графике?

При разумном количестве спрайтов нет. Поверхности (Surface) в Pygame живут в оперативной памяти, и blit, это быстрое копирование пикселей, а не программный рендеринг. На тысяче одновременно движущихся объектов вы можете упереться в производительность Python, но для платформера, top-down шутера или tower defence запас прочности есть. Если нужно выжать максимум, используйте pygame.sprite.Group с автоматической отрисовкой и dirty-rectangles для частичного обновления экрана.

Можно ли в Pygame добавить звук и музыку?

Да, из коробки. Модуль pygame.mixer умеет проигрывать WAV и MP3. Звук выстрела запускается через pygame.mixer.Sound("shoot.wav").play(), а фоновая музыка загружается через pygame.mixer.music.load("theme.mp3") и pygame.mixer.music.play(-1) (флаг -1 зацикливает). Единственный нюанс: pygame.mixer.init() нужно вызвать до загрузки звуков, и для MP3 на Linux может потребоваться библиотека libmpg123.

Есть ли смысл учить Pygame в 2026 году, когда есть Godot и Unity?

Абсолютно. Pygame не конкурент Godot, это учебный инструмент и лёгкая прослойка для 2D-прототипов. Вы не учите C# ради того, чтобы подвигать квадратик, и не разбираетесь в нодовой системе ради Pong-а. Pygame даёт понимание того, как игры работают на нижнем уровне: игровой цикл, буферизация кадров, коллизии. Программисты, стартовавшие с Pygame, легче осваивают Unity и Godot, потому что видят за абстракциями движка живую механику. На Pygame пишут реальные инди-проекты, включая коммерческие, небольшой платформер или пазл можно выпустить в Steam, не притрагиваясь к C++.

Что делать, если спрайт уходит за край экрана?

Добавьте проверку границ в метод move(): если self.x < 0, приравняйте к 0; если self.x + ширина_спрайта > WIDTH, приравняйте к WIDTH - ширина_спрайта. То же для Y. Это называется clamping, и без него персонаж рано или поздно уедет в невидимую область. В более продвинутых играх границами служат стены уровня, определённые через тайловую сетку или массив коллизий.

Готовы запустить свою первую игру?

Скопируйте код из раздела «Пишем первый код», сохраните в game.py, положите рядом любую картинку-спрайт, и через несколько секунд вы увидите окно с движущимся персонажем. Это и есть точка входа в геймдев: не читать, а запустить и начать крутить параметры.

Поменяйте WIDTH и HEIGHT, окно станет больше. Задайте player.speed = 10, персонаж ускорится. Замените WHITE на (35, 35, 35), получите тёмный фон. Поэкспериментируйте, и вы поймёте, что игровая программа, не магия, а последовательность шагов, которые вы контролируете.

Когда освоите движение, беритесь за столкновения (pygame.sprite.collide_rect()), анимацию (смена кадров спрайт-листа) и процедурную генерацию уровней. К старту хватит одного файла game.py и желания разобраться, как оно устроено.