Создание стартового меню и экрана «Game Over» в PyGame
Кратко

О чём эта статья
- Минималистичный однопользовательский пример с игроком и препятствием.
- Как добавить стартовое меню и экран «Game Over» (завершения игры).
- Улучшенная версия кода с обработкой состояния, FPS и корректным сбросом игры.
- Практические советы по UX, чек-листы и альтернативные подходы.
Требования и установка
Потребуется Python 3.7+ и библиотека PyGame. Установить PyGame можно так:
pip install pygameОпределение: PyGame — это библиотека для вывода 2D-графики, обработки ввода и звука в Python.
Быстрая архитектура решения
Мы используем простую машину состояний (state machine):
- start_menu — показываем стартовый экран и ждём начала игры;
- game — основной цикл игры с физикой/логикой и проверкой столкновений;
- game_over — показываем экран с выбором: перезапустить или выйти.
Важно: состояние хранится в одной переменной (game_state). Это упрощает добавление паузы или экрана настроек.
Важно: для корректной работы всегда инициализируйте все флаги (например, game_over) и используйте pygame.time.Clock() для стабильного FPS.
Минимальный пример игры (объяснение идеи)
Идея простая: у нас есть прямоугольный игрок, который двигается влево/вправо, и прямоугольное препятствие. При пересечении областей возникает столкновение — переходим в состояние game_over.
Ниже — улучшённый и рабочий пример кода. Я привёл его аккуратно, с комментариями и стабильной обработкой ввода.
import pygame
import sys
# Инициализация
pygame.init()
FPS = 60
clock = pygame.time.Clock()
# Окно
SCREEN_W, SCREEN_H = 750, 450
screen = pygame.display.set_mode((SCREEN_W, SCREEN_H))
pygame.display.set_caption('My Game')
# Игровые параметры
obstacle = pygame.Rect(400, 350, 40, 40)
player = pygame.Rect(200, 350, 20, 20)
PLAYER_SPEED = 5
# Состояние игры
game_state = 'start_menu' # варианты: 'start_menu', 'game', 'game_over'
score = 0
# Шрифты
font_large = pygame.font.SysFont('arial', 40)
font_small = pygame.font.SysFont('arial', 24)
# Вспомогательные функции
def draw_text_center(text, font, color, y):
surf = font.render(text, True, color)
x = SCREEN_W // 2 - surf.get_width() // 2
screen.blit(surf, (x, y))
def reset_game():
global player, obstacle, score
player.topleft = (200, 350)
obstacle.topleft = (400, 350)
score = 0
def draw_start_menu():
screen.fill((0, 0, 0))
draw_text_center('My Game', font_large, (255, 255, 255), SCREEN_H // 2 - 60)
draw_text_center('Нажмите ПРОБЕЛ для старта', font_small, (200, 200, 200), SCREEN_H // 2)
draw_text_center('Используйте ← → для управления', font_small, (150, 150, 150), SCREEN_H // 2 + 30)
pygame.display.flip()
def draw_game_over():
screen.fill((0, 0, 0))
draw_text_center('Game Over', font_large, (255, 80, 80), SCREEN_H // 2 - 40)
draw_text_center(f'Ваш счёт: {score}', font_small, (255, 255, 255), SCREEN_H // 2)
draw_text_center('R — Перезапустить Q — Выйти', font_small, (200, 200, 200), SCREEN_H // 2 + 40)
pygame.display.flip()
# Основной цикл
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if game_state == 'start_menu' and event.key == pygame.K_SPACE:
reset_game()
game_state = 'game'
elif game_state == 'game_over':
if event.key == pygame.K_r:
reset_game()
game_state = 'start_menu'
elif event.key == pygame.K_q:
running = False
# Логика игры
if game_state == 'start_menu':
draw_start_menu()
elif game_state == 'game':
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.x -= PLAYER_SPEED
if keys[pygame.K_RIGHT]:
player.x += PLAYER_SPEED
# Ограничение по экрану
player.x = max(0, min(player.x, SCREEN_W - player.width))
# Проверка столкновения
if player.colliderect(obstacle):
game_state = 'game_over'
# Простейший рендер
screen.fill((0, 0, 0))
pygame.draw.rect(screen, (255, 0, 0), obstacle)
pygame.draw.rect(screen, (0, 255, 0), player)
pygame.display.flip()
elif game_state == 'game_over':
draw_game_over()
clock.tick(FPS)
pygame.quit()
sys.exit()Пояснение ключевых мест в коде
- pygame.time.Clock() и clock.tick(FPS) — поддерживают постоянную частоту кадров и стабилизируют поведение на разных машинах.
- События KEYDOWN используются для управления экранами (чтобы одиночное нажатие сработало один раз).
- player.colliderect(obstacle) — удобный метод для проверки столкновения прямоугольников.
- reset_game() — централизованный сброс игрового состояния.
Шпаргалка команд и клавиш
- Пробел — старт из стартового меню.
- Стрелки ← → — движение игрока в игровом режиме.
- R — вернуться в стартовое меню с экрана Game Over.
- Q — выйти из игры.
Альтернативные подходы
- Использовать события мыши и кликабельные кнопки вместо клавиатуры для меню — удобнее на ПК с мышью.
- Вынести состояние игры в отдельный класс StateManager для сложных проектов с множеством экранов.
- Управлять меню через UI-библиотеки (например, pygame_menu) — экономит время при сложных интерфейсах.
Когда этот минималистичный подход не подходит:
- Если у вас сложный UI с анимациями, с учётом локализации и скалирования — стоит использовать специализированную библиотеку меню.
- Для сетевой игры логика рестарта должна синхронизироваться по сети; локальное переключение state будет недостаточно.
UX и визуальные рекомендации
- Используйте легко читаемые шрифты и достаточный контраст (цвет текста vs фон).
- Давайте пользователю явный фидбек (звук или анимация) при старте и смерти.
- Делайте короткие подсказки по управлению на стартовом экране.
- При перезапуске восстанавливайте начальные позиции и — при необходимости — таймеры.
Чек-листы по ролям
Разработчик
- Инициализировал все переменные состояния.
- Использует clock.tick(FPS).
- Проверил отсутствие утечек событий.
Дизайнер интерфейса
- Тестировал читаемость текста при разных разрешениях.
- Проверил контраст и цветовую гармонию.
Тестировщик
- Нажатия клавиш в стартовом меню срабатывают один раз.
- При столкновении игра переходит в game_over и блокирует вход в game до перезапуска.
Критерии приёмки
- Стартовое меню отображается и реагирует на ПРОБЕЛ одним нажатием.
- В игровом режиме движение по стрелкам корректно и ограничено границами экрана.
- При столкновении отображается экран «Game Over» с опциями R и Q.
- После выбора R игра возвращается в стартовое меню, все параметры сброшены.
Модель зрелости (мелкие шаги развития)
- Уровень 0: базовый state machine с 3 состояниями (start, game, game_over).
- Уровень 1: добавление очков, звуковых эффектов и ограничений/жизней.
- Уровень 2: сохранение результатов, анимации переходов, экран настроек.
- Уровень 3: интеграция меню с системой уровней, достижениями и локализацией.
Когда стоит усложнить архитектуру
- Когда число экранов > 5: переход на менеджер экранов оправдан.
- Когда логика меню становится реактивной (анимации, переходы): разделяйте рендер и логику.
Мини-методология разработки UI для PyGame (быстрое руководство)
- Спроектируйте состояния и переходы (state diagram).
- Нарисуйте макет стартового экрана и экрана окончания.
- Реализуйте базовую логику на клавишах.
- Добавьте ограничения частоты кадров и функции сброса.
- Протестируйте на нескольких разрешениях.
- Соберите отзывы и улучшите читаемость/контраст.
Примеры тест-кейсов
- Нажать ПРОБЕЛ в стартовом меню — игра начинает.
- Нажать и удерживать стрелку — игрок движется, не выходит за экран.
- Врезаться в препятствие — появляется Game Over.
- Нажать R на Game Over — вернуться в стартовое меню, позиции сброшены.
Решение типичных ошибок
Проблема: многократное срабатывание старта при удержании пробела. Решение: использовать KEYDOWN вместо key.get_pressed() для меню.
Проблема: переменные неинициализированы (game_over не объявлен). Решение: всегда задавайте начальные значения и используйте reset_game().
Простое дерево принятия решения для выбора реализации меню
flowchart TD
A[Нужен простой старт?] -->|Да| B[Сделать текcтовое меню + KEYDOWN]
A -->|Нет| C[Нужны кликабельные кнопки]
C --> D[Использовать pygame_menu или своя реализация кнопок]
B --> E[Добавить инструкции и пробельный запуск]Резюме
- Разделяйте состояние игры и логику рендера — это упрощает добавление новых экранов.
- Используйте KEYDOWN для экранов меню, а key.get_pressed() для непрерывного движения в игре.
- Поддерживайте фиксированный FPS через clock.tick() для предсказуемых эффектов.
Итог
Добавление стартового меню и экрана «Game Over» — это небольшой шаг к более законченной игре. Даже в минималистичном проекте правильная организация состояний, единый способ сброса и контролируемая частота кадров заметно улучшают опыт разработки и игры. Начните с предложенного кода, протестируйте на целевых устройствах и по мере роста проекта переходите к менеджеру экранов и библиотекам UI.
Похожие материалы
Как включить авто‑субтитры в TikTok
Higan для SNES на Ubuntu — точная эмуляция
Winget: как использовать Windows Package Manager
Установка и настройка тем в Windows
Показать путь папки в Finder на Mac