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

Пауэр-апы и коллекционные предметы в Pygame

6 min read Game Dev Обновлено 20 Dec 2025
Пауэр‑апы и коллекции в Pygame
Пауэр‑апы и коллекции в Pygame

игрок в аркадной игре с джойстиком и пикселями

Пауэр‑апы и коллекционные предметы (collectibles) значительно улучшают игровой процесс: создают задачи, стимулируют игрока принимать решения и дают почувствовать прогресс. Pygame предоставляет гибкие средства для реализации таких объектов — от простых коллизий до таймеров и визуальных индикаторов.

Основная идея и варианты формата

Цель: расширить базовую аркадную игру, где игрок двигается влево/вправо и избегает врага, добавив:

  • Коллекционные предметы, дающие очки.
  • Пауэр‑апы, дающие временное преимущество (например, щит, который уничтожает врага при столкновении).
  • Таймеры длительности и визуальные индикаторы.

Варианты реализации: объекты-спрайты (pygame.sprite.Sprite), простые прямоугольные/окружные коллизии, системы предметов с редкостью, накопительные эффекты и т. д.

Hints: термины в одну строку

  • Коллизия: проверка пересечения областей спрайтов.
  • Респаун: генерация объекта в новой позиции после исчезновения.
  • Таймер: отсчёт времени в миллисекундах через pygame.time.get_ticks().

Создаём простую игру (основа)

Перед началом установите Pygame:

pip install pygame

Ниже — минимальная игра, на которой мы будем наращивать функции (движение игрока, враг, коллизия завершает игру). Сохраните как main.py или используйте как основу.

import pygame
import random

# Инициализация Pygame
pygame.init()

# Параметры окна
window_width = 800
window_height = 600
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("My Game")

# Игрок
player_width = 50
player_height = 50
player_x = (window_width - player_width) // 2
player_y = window_height - player_height - 10
player_speed = 5

# Враг
enemy_width = 50
enemy_height = 50
enemy_x = random.randint(0, window_width - enemy_width)
enemy_y = 50
enemy_speed = 3

# Игровой цикл
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Движение игрока
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] and player_x > 0:
        player_x -= player_speed
    if keys[pygame.K_RIGHT] and player_x < window_width - player_width:
        player_x += player_speed

    # Движение врага
    enemy_y += enemy_speed
    if enemy_y > window_height:
        enemy_x = random.randint(0, window_width - enemy_width)
        enemy_y = 0

    # Проверка коллизии игрока с врагом
    if (player_x < enemy_x + enemy_width) and \
       (player_x + player_width > enemy_x) and \
       (player_y < enemy_y + enemy_height) and \
       (player_y + player_height > enemy_y):
        running = False

    # Отрисовка
    window.fill((0, 0, 0))
    player_pos = (player_x, player_y, player_width, player_height)
    enemy_pos = (enemy_x, enemy_y, enemy_width, enemy_height)
    pygame.draw.rect(window, (255, 255, 255), player_pos)
    pygame.draw.rect(window, (255, 0, 0), enemy_pos)
    pygame.display.update()

pygame.quit()

Ниже — изображение результата этого базового кода:

простой аркадный экран с игроком и врагом

Добавляем коллекционные предметы (collectibles)

Задача: при пересечении с игроком предмет исчезает и начисляет, например, 10 очков. Нужно отслеживать коллизии между игроком и предметом и обновлять счёт.

Сниппет для collectibles.py — ключевые дополнения:

# Коллекционный предмет
collectible_width = 30
collectible_height = 30
collectible_x = random.randint(0, window_width - collectible_width)
collectible_y = 50

# Счёт
score = 0
font = pygame.font.Font(None, 36)

# ... внутри игрового цикла ...
# Коллизия игрока с коллекционным предметом
if (player_x < collectible_x + collectible_width) and \
   (player_x + player_width > collectible_x) and \
   (player_y < collectible_y + collectible_height) and \
   (player_y + player_height > collectible_y):
    collectible_x = random.randint(0, window_width - collectible_width)
    collectible_y = 50
    score += 10

# Отрисовка коллекционного предмета (как круг)
collectible_pos = (collectible_x, collectible_y)
pygame.draw.circle(window, (0, 255, 0), collectible_pos, collectible_width)

# Отрисовка счёта
score_text = font.render("Score: " + str(score), True, (255, 255, 255))
window.blit(score_text, (10, 10))

Результат — предметы, которые игрок собирает за очки:

игра pygame с коллекционным предметом, врагом и игроком

Добавляем пауэр‑апы (power-ups)

Идея: при сборе пауэр‑апа у игрока появляется временный эффект (щит), который при столкновении с врагом уничтожает врага. Основные компоненты: флаг активности (shield_active) и время активации (shield_timer).

Ключевые фрагменты для powerups.py:

# Пауэр-ап
powerup_width = 40
powerup_height = 40
powerup_x = random.randint(0, window_width - powerup_width)
powerup_y = 50
shield_active = False
shield_timer = 0

# ... внутри игрового цикла ...
# Проверка столкновения с пауэр-апом
collision_powerup = (player_x < powerup_x + powerup_width) and \
                   (player_x + player_width > powerup_x) and \
                   (player_y < powerup_y + powerup_height) and \
                   (player_y + player_height > powerup_y)

if collision_powerup:
    powerup_x = random.randint(0, window_width - powerup_width)
    powerup_y = 50
    shield_active = True
    shield_timer = pygame.time.get_ticks()

# Таймер для деактивации щита
if shield_active:
    current_time = pygame.time.get_ticks()
    if current_time - shield_timer > 5000:  # 5000 мс = 5 с
        shield_active = False

# Отрисовка пауэр-апа (как треугольник)
x1 = powerup_x + powerup_width / 2
y1 = powerup_y
x2 = powerup_x
y2 = powerup_y + powerup_height
x3 = powerup_x + powerup_width
y3 = powerup_y + powerup_height
pygame.draw.polygon(window, (255, 255, 0), [(x1, y1), (x2, y2), (x3, y3)])

# Коллизия с врагом, если щит активен
collision_shield = shield_active and \
                   (player_x < enemy_x + enemy_width) and \
                   (player_x + player_width > enemy_x) and \
                   (player_y < enemy_y + enemy_height) and \
                   (player_y + player_height > enemy_y)

if collision_shield:
    enemy_x = random.randint(0, window_width - enemy_width)
    enemy_y = 0

Результат — пауэр‑апы, которые дают временное преимущество:

игра pygame с пауэр-апом, коллекционным предметом, врагом и игроком

Таймер респауна пауэр‑апов

Если вы хотите, чтобы пауэр‑апы исчезали и появлялись снова через заданный интервал, используйте таймер респауна.

# Таймер респауна пауэр-апа
powerup_respawn_timer = 0

# ... внутри игрового цикла ...
if not shield_active:
    current_time = pygame.time.get_ticks()
    if current_time - powerup_respawn_timer > 3000:  # 3 секунды
        powerup_x = random.randint(0, window_width - powerup_width)
        powerup_y = 50
        powerup_respawn_timer = pygame.time.get_ticks()

Визуализация таймера пауэр‑апа (бар)

Покажите игроку оставшуюся длительность пауэр‑апа с помощью полосы.

# Полоса для индикации оставшегося времени пауэр-апа
bar_width = 100
bar_height = 10
bar_x = window_width - bar_width - 10
bar_y = 10

# ... внутри игрового цикла ...
if shield_active:
    current_time = pygame.time.get_ticks()
    elapsed_time = current_time - shield_timer
    timer_progress = max(0, (5000 - elapsed_time) / 5000)  # от 1 до 0
    bar_rect = pygame.Rect(bar_x, bar_y, bar_width * timer_progress, bar_height)
    pygame.draw.rect(window, (0, 255, 255), bar_rect)

Результат — полоса, убывающая по мере истечения эффекта:

бар таймера в pygame с игроком, врагом, пауэр-апом и предметом

Лучшие практики при добавлении пауэр‑апов и коллекционных предметов

Ниже — расширенное руководство с практическими советами, примерами и шаблонами.

Визуальная различимость

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

Баланс и сложность

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

  • Лёгкий: частые коллекционные предметы, редкие пауэр‑апы.
  • Средний: средняя частота и длительность.
  • Сложный: редкие коллекционные предметы и короткие пауэр‑апы.

Обратная связь и вознаграждения

Добавляйте звук, частицы, шкалу опыта или всплывающую метку «+10», чтобы игрок понял, что получил награду. Вознаграждение может быть: очки, жизнь, ускорение, временный щит, замедление врагов и т.д.

Таймеры и продолжительность

Используйте pygame.time.get_ticks() (возвращает миллисекунды). Всегда проверяйте переполнение: храните только время активации и вычисляйте разницу.

Тестируйте и итеративно настраивайте

Проводите короткие сессии тестирования: 5–10 раундов с разными настройками. Собирайте метрики (время выживания, средний счёт, частота использования пауэр‑апов) и правьте значения.

Когда это не сработает: типичные ограничения и контрпримеры

  • Когда коллизии слишком точечные (pixel-perfect) — простая AABB проверка может давать неожиданные результаты. Решение: использовать pygame.sprite.collide_mask или увеличить хитбокс.
  • Если на экране слишком много объектов — производительность падает. Решение: спрайтовые группы, spatial hashing или ограничение числа одновременно активных объектов.
  • Когда игрок слишком часто получает один и тот же эффект — добавьте систему редкости и «временную блокировку» (cooldown) на появление повтора.

Альтернативные подходы

  1. Спрайтовая система: реализовать пауэр‑апы и коллекции как классы, наследующие pygame.sprite.Sprite. Это упростит управление группами, коллизиями и рендером.
  2. Компонентная архитектура: хранить эффекты как компоненты сущности (например, ShieldComponent с таймером).
  3. Событийно‑ориентированная модель: при сборе отправлять событие, которое обрабатывают системы (звук, UI, логика).

Ментальные модели и эвристики

  • Правило 3: игрок должен увидеть объект, понять его эффект и получить вознаграждение не более чем за 3 секунды игрового времени.
  • Правило риска/вознаграждения: мощный эффект — это рискованный или редкий спавн.
  • Экономика внимания: выделите 1–2 наиболее ценных объекта на экран, чтобы не перегружать игрока.

Мини‑методология реализации (шаги)

  1. Реализовать базовую игру (игрок, враг).
  2. Добавить один тип коллекционного предмета с начислением очков.
  3. Добавить один тип пауэр‑апа с временной активацией и индикатором.
  4. Вынести общую логику коллизий в функции/классы.
  5. Провести A/B тест с разными тиками длительности и частоты респауна.
  6. Итеративно настраивать визуальные эффекты и звук.

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

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

  • Реализовать корректные AABB коллизии или маски.
  • Добавить таймеры через get_ticks.
  • Оптимизировать рендер и логику при большом количестве объектов.

Дизайнер:

  • Задать цветовую семантику.
  • Определить редкость и баланс эффектов.
  • Подготовить подсказки и иконки.

Тестировщик:

  • Проверить выпадение предметов на разных разрешениях.
  • Тестировать крайние случаи (мгновенные повторные коллизии).
  • Замерить влияние на производительность.

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

  • Коллекционные предметы корректно исчезают и начисляют очки при коллизии.
  • Пауэр‑ап активируется и деактивируется через заданное время.
  • При активном щите столкновение с врагом перезапускает врага (или уничтожает его) без завершения игры.
  • Индикатор времени пауэр‑апа отображается и убывает синхронно с таймером.
  • Нет утечек объектов: объект либо активен, либо корректно респаунится/удаляется.

Шаблоны и фрагменты (cheat sheet)

Функция проверки коллизии AABB:

def aabb_collision(x1, y1, w1, h1, x2, y2, w2, h2):
    return (x1 < x2 + w2) and (x1 + w1 > x2) and (y1 < y2 + h2) and (y1 + h1 > y2)

Удобная функция респауна по оси X:

def respawn_x(width, object_width):
    return random.randint(0, width - object_width)

Унифицированный код активации пауэр‑апа:

def activate_powerup(duration_ms):
    global shield_active, shield_timer
    shield_active = True
    shield_timer = pygame.time.get_ticks()
    return duration_ms

Тестовые случаи и приёмочные критерии

  1. Игрок собирает коллекционный предмет — счёт увеличивается ровно на ожидаемую величину.
  2. Пауэр‑ап активируется и длится примерно заданное число миллисекунд (+- небольшой лаг от кадра).
  3. При истечении таймера эффект отключается и полоса индикатора опускается до нуля.
  4. Повторный сбор пауэр‑апа до окончания предыдущего или после него — ведёт себя согласно дизайну (накопление/обновление/блокировка).
  5. Нагрузка: при 50 одновременных мелких объектов частота кадров не должна падать критически (варьируется по устройству).

Советы по миграции и совместимости

  • Для проектов, которые планируются расширять, используйте pygame.sprite.Group и Sprite-классы сразу.
  • Если планируете портировать на Web (Pyodide/emscripten), учтите ограничения по времени и звуку.

Итог

Добавление коллекционных предметов и пауэр‑апов в Pygame — задача, которая повышает вовлечённость игроков и открывает поле для дизайнерских решений. Начинайте с простой реализации (AABB коллизии, одиночный пауэр‑ап, счёт) и постепенно выносите логику в классы, добавляйте таймеры и индикаторы. Тестируйте разные частоты появления и длительности, чтобы найти баланс.

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

Включите это в свой проект как шаг за шагом: сначала коллекционные предметы, затем пауэр‑апы, потом визуализацию и тестирование. Удачи с разработкой!

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

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

Лучшие бесплатные экшены для Photoshop
Графический Дизайн

Лучшие бесплатные экшены для Photoshop

Live Speech на iPhone, iPad и Mac — настройка и советы
Доступность

Live Speech на iPhone, iPad и Mac — настройка и советы

Сжать видео для веба через Windows Movie Maker
Руководства

Сжать видео для веба через Windows Movie Maker

Директивы Angular: ngIf, ngFor, ngClass и др.
Angular

Директивы Angular: ngIf, ngFor, ngClass и др.

Установка PostgreSQL на Ubuntu — пошагово
Базы данных

Установка PostgreSQL на Ubuntu — пошагово

Переключение Dev и Beta каналов в Windows 11
Инструкции

Переключение Dev и Beta каналов в Windows 11