Гид по технологиям

Уровни в PyGame: проектирование и подключение

6 min read Game Dev Обновлено 04 Jan 2026
Уровни в PyGame: планирование и подключение
Уровни в PyGame: планирование и подключение

двое разработчиков планируют уровни разной сложности на белой доске

Уровни — важная составляющая большинства видеоигр. Они задают структуру, обеспечивают прогресс и разнообразие, а также повышают вовлечённость игрока. PyGame — популярная библиотека на Python для разработки 2D-игр — предоставляет инструменты, с помощью которых можно быстро создать и связать несколько уровней. Хорошо продуманный уровень захватывает игрока, создаёт ощущение продвижения и награды за усилия.

Планирование и проектирование уровней

Перед созданием уровней важно их спланировать. Планирование поможет создать структуру игры, плавно увеличивать сложность и обеспечить согласованность механик. Ключевые факторы при планировании:

  • Механики игры: прыжки, ускорение, двойной прыжок, взаимодействие с врагами.
  • Нарратив и темп: где и как игрок узнаёт новую механику.
  • Архитектура уровней: линейные секции, ветвления, секреты.
  • Баланс сложности: первая встреча с угрозой должна быть обучающей.

Пример: в платформере следует продумать расположение платформ, врагов и препятствий, маршруты авторов (paths), точки чекпоинтов и зоны возврата. Учтите размеры игрока и физику (высота прыжка, скорость), чтобы уровни были проходимы, но требовали мастерства.

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

Простейшие два уровня — исходный код

Ниже сохранены оригинальные примеры кода двух очень простых уровней. Убедитесь, что pip установлен, и затем выполните:

pip install pygame

Первый уровень:

import pygame  
  
pygame.init()  
  
# Define constants  
SCREEN_WIDTH = 800  
SCREEN_HEIGHT = 600  
PLATFORM_WIDTH = 100  
PLATFORM_HEIGHT = 20  
PLAYER_WIDTH = 50  
PLAYER_HEIGHT = 50  
PLATFORM_COLOR = (255, 255, 255)  
PLAYER_COLOR = (255, 0, 0)  
  
# Create the screen  
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))  
  
# Create the platform  
platform = pygame.Rect(350, 500, PLATFORM_WIDTH, PLATFORM_HEIGHT)  
  
# Create the player  
player = pygame.Rect(375, 450, PLAYER_WIDTH, PLAYER_HEIGHT)  
  
# Game loop  
running = True  
while running:  
    for event in pygame.event.get():  
        if event.type == pygame.QUIT:  
            running = False  
        elif event.type == pygame.KEYDOWN:  
            if event.key == pygame.K_LEFT:  
                player.move_ip(-10, 0)  
            elif event.key == pygame.K_RIGHT:  
                player.move_ip(10, 0)  
  
    # Fill the screen with black color  
    screen.fill((0, 0, 0))  
  
    # Draw the platform  
    pygame.draw.rect(screen, PLATFORM_COLOR, platform)  
  
    # Draw the player  
    pygame.draw.rect(screen, PLAYER_COLOR, player)  
  
    # Update the screen  
    pygame.display.flip()  
  
pygame.quit()

Второй уровень (тот же код, но с изменёнными позициями платформы и игрока):

import pygame  
  
pygame.init()  
  
# Define constants  
SCREEN_WIDTH = 800  
SCREEN_HEIGHT = 600  
PLATFORM_WIDTH = 150  
PLATFORM_HEIGHT = 20  
PLAYER_WIDTH = 50  
PLAYER_HEIGHT = 50  
PLATFORM_COLOR = (255, 255, 255)  
PLAYER_COLOR = (255, 0, 0)  
  
# Create the screen  
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))  
  
# Create the platform  
platform = pygame.Rect(200, 500, PLATFORM_WIDTH, PLATFORM_HEIGHT)  
  
# Create the player  
player = pygame.Rect(225, 450, PLAYER_WIDTH, PLAYER_HEIGHT)  
  
# Game loop  
running = True  
while running:  
    for event in pygame.event.get():  
        if event.type == pygame.QUIT:  
            running = False  
        elif event.type == pygame.KEYDOWN:  
            if event.key == pygame.K_LEFT:  
                player.move_ip(-10, 0)  
            elif event.key == pygame.K_RIGHT:  
                player.move_ip(10, 0)  
  
    # Fill the screen with black color  
    screen.fill((0, 0, 0))  
  
    # Draw the platform  
    pygame.draw.rect(screen, PLATFORM_COLOR, platform)  
  
    # Draw the player  
    pygame.draw.rect(screen, PLAYER_COLOR, player)  
  
    # Update the screen  
    pygame.display.flip()  
  
pygame.quit()

Эти примеры демонстрируют базовый принцип: уровни — это разные конфигурации объектов (платформы, враги, предметы). Далее покажем, как переключать уровни и передавать данные.

Подключение разных уровней

Чтобы переключать уровни, заведите переменную, которая хранит номер (или идентификатор) текущего уровня, и используйте условные операторы или диспетчер для вызова отрисовки и логики конкретного уровня. Один из простых подходов — проверять попадание игрока в зону выхода и менять current_level.

Оригинальный пример модифицированного игрового цикла:

current_level = 1  
  
# Draw the platform and the player based on the current level  
if current_level == 1:  
    pygame.draw.rect(screen, PLATFORM_COLOR, platform1)  
    pygame.draw.rect(screen, PLAYER_COLOR, player)  
    # Check if the player has reached the end of the level  
    if player.colliderect(platform1) == False:  
        current_level = 2  
elif current_level == 2:  
    pygame.draw.rect(screen, PLATFORM_COLOR, platform2)  
    pygame.draw.rect(screen, PLAYER_COLOR, player)  
    # Check if the player has reached the end of the level  
    if player.colliderect(platform2) == True:  
        running = False

Замечания по этому фрагменту:

  • Условие player.colliderect(platform1) == False выглядит необычно для проверки завершения уровня — обычно проверяют попадание в конечную зону (exit zone). Следует использовать явную «зону выхода» Rect и проверять colliderect == True.
  • Для масштабируемости удобнее вынести логику уровней в классы или функции и иметь LevelManager.

Совместное использование данных между уровнями

Чтобы сохранить состояние (например позицию игрока, количество жизней, собранные предметы) между сменами уровней, используют общий модуль данных. В статье предлагается модуль game_data.py с глобальными переменными.

Содержимое game_data.py:

player_pos = (0, 0)

Использование в уровне (фрагмент):

import pygame  
import game_data  
  
  
# Create the player  
player = pygame.Rect(game_data.player_pos[0], game_data.player_pos[1], PLAYER_WIDTH, PLAYER_HEIGHT)  
  
# Game loop  
running = True  
while running:  
    # Draw the player   
    pygame.draw.rect(screen, PLAYER_COLOR, player)  
  
    # Update the player's position in the game_data module  
    game_data.player_pos = (player.x, player.y)

Это простой и рабочий способ для небольших проектов. При росте проекта лучше перейти на хранение состояния в объекте игры или сериализуемой структуре (JSON, pickle или собственный save/load).

Рекомендации по архитектуре уровней

Ниже — практические советы, которые подойдут большинству 2D-платформеров и простых игр на PyGame.

  • Изолируйте графику и логику уровня. Файлы уровней должны описывать расположение объектов и метаданные (спавн, чекпоинты, зоны выхода).
  • Храните уровни в отдельных JSON/YAML/CSV-файлах для быстрой правки без перекомпиляции.
  • Сделайте LevelManager: регистрирует уровни, загружает и выгружает ресурсы, восстанавливает состояние игрока.
  • Добавьте точки контрольных сохранений (чекпоинты) и явную зону выхода.
  • Для тестирования уровней создавайте «режим просмотра», где можно быстро перемещать игрока и проверять коллизии.

Пример простого LevelManager

Ниже — компактный пример диспетчера уровней, который хранит список уровней и переключает их по индексу. Этот код — рекомендация, его можно адаптировать под вашу архитектуру.

class LevelManager:
    def __init__(self, levels):
        self.levels = levels
        self.current = 0

    def current_level(self):
        return self.levels[self.current]

    def next_level(self):
        if self.current + 1 < len(self.levels):
            self.current += 1
            return True
        return False

# Пример использования:
# manager = LevelManager([level1, level2])
# while running:
#     lvl = manager.current_level()
#     lvl.update()
#     if lvl.finished:
#         if not manager.next_level():
#             running = False

Этот паттерн отделяет управление последовательностью уровней от самой игровой логики.

Чек-листы по ролям

Дизайнер уровня:

  • Набросать маршрут игрока и ключевые точки.
  • Убедиться, что обучение новым механикам находится в начале уровня.
  • Прописать зону выхода и чекпоинты.

Разработчик:

  • Вынести конфигурацию уровня в отдельный файл.
  • Реализовать загрузчик и интерфейс Level API (load/unload/update/draw).
  • Добавить обработку сохранения состояния.

Тестер:

  • Проверить прохождение от старта до выхода без багов.
  • Проверить откат к чекпоинту.
  • Тестировать на граничных позициях игрока и коллизиях с объектами.

Критерии приёмки

  • Игрок может пройти уровень от старта до выхода без блокировок.
  • Сохранённая позиция игрока корректно восстанавливается после перехода уровня.
  • Не возникает утечек памяти при частой смене уровней.
  • Все интерактивные объекты имеют ожидаемое поведение.

Тестовые сценарии

  • Проверка перехода уровней: игрок пересекает зону выхода — уровень меняется.
  • Проверка сохранения позиции: сохранить позицию, перезагрузить уровень, убедиться, что позиция восстановлена.
  • Граничные условия: игрок попадает в угол экрана — коллизии не ломают физику.

Альтернативные подходы и когда это не сработает

Альтернативы:

  • Сцены (Scene Graph) — полезно для сложных игр с емким деревом объектов.
  • FSM (конечные автоматы) для управления состояниями игры (меню, пауза, уровень).
  • Использование движка (Godot, Unity) для проектов с более высокой сложностью.

Когда простой модуль game_data не подойдёт:

  • Мультиплеер или клиент-серверная архитектура — тут требуется синхронизация состояния и сериализация через протокол.
  • Большие проекты с сотнями уровней — лучше использовать систему ресурсов и загрузку по требованию.

Частые ошибки и рекомендации по отладке

  • Отсутствие явной зоны выхода. Решение: создайте Rect exit_zone и проверяйте colliderect.
  • Сохранение состояния в локальных переменных уровня. Решение: централизовать состояние в менеджере игры.
  • Неправильная подписка на события ввода при смене уровней. Решение: очищать и перенастраивать обработчики ввода при загрузке уровня.

Важно: не храните большой объём данных в глобальных переменных без контроля — это усложняет тестирование и приводит к трудноуловимым багам.

Краткая методология для итерации уровней

  1. Напишите бумажный прототип и пройдите маршрут как игрок.
  2. Сделайте «голый» прототип в PyGame с прямоугольниками и базовой физикой.
  3. Игрок/тестер проходит уровень, помечайте точки проблем.
  4. Перенесите конфигурацию в файл (JSON) и добавьте возможность горячей перезагрузки уровня.
  5. Полируйте визуал и звуки.

Однострочные определения (глоссарий)

  • Уровень — игровая сцена с набором объектов и задач.
  • Чекпоинт — точка сохранения прогресса внутри уровня.
  • Зона выхода — область, при пересечении которой уровень считается пройденным.

Краткое резюме

Добавление уровней делает игру интереснее и удерживает игрока. Начинайте с простых конфигураций, применяйте LevelManager для управления последовательностью, храните состояние в централизованном месте и проверяйте переходы и сохранение позиции через тесты. По мере роста проекта переходите к более формальным подходам (сцены, загрузчики ресурсов, сериализация).

Дополнительно: сохраняйте версии уровней в системе контроля версий, используйте текстовые форматы для конфигураций (JSON/YAML) и обеспечьте инструменты для быстрого редактирования и тестирования уровней.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство