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

Прокручивающиеся фоны в Pygame — параллакс и оптимизация

6 min read Разработка игр Обновлено 20 Dec 2025
Прокручивающиеся фоны в Pygame — параллакс и оптимизация
Прокручивающиеся фоны в Pygame — параллакс и оптимизация

Кратко

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

игра на широком мониторе с контроллером

Прокручивающиеся фоны существенно повышают визуальную привлекательность и ощущение глубины в игре. Они создают иллюзию движения и делают мир более живым. В Pygame реализовать скроллинг можно в несколько простых шагов — от прямой заливки цветом до слоёв с изображениями и параллакса.

Что вы получите

  • Рабочую структуру простого проекта Pygame с прокручивающимся фоном;
  • Варианты реализации: цветные прямоугольные слои, несколько слоёв параллакса, изображение-фон с масштабированием и оптимизацией;
  • Советник по производительности и чек-листы для тестирования на разных устройствах.

1. Создаём простую игру (каркас)

Начните с минимального примера, где игрок может двигаться влево и вправо, а на экране есть две платформы. Создайте файл simple-game.py.

Опишите начальную настройку Pygame, создайте размеры экрана, задайте стартовые координаты игрока и скорость движения, определите платформы с помощью pygame.Rect.

Пример структуры (псевдо/каркас):

import pygame
pygame.init()

screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
clock = pygame.time.Clock()

player_x, player_y = 100, screen_height - 150
player_speed = 5

rect1 = pygame.Rect(50, screen_height - 100, 200, 10)
rect2 = pygame.Rect(screen_width - 250, screen_height - 200, 200, 10)

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]:
        player_x -= player_speed
    if keys[pygame.K_RIGHT]:
        player_x += player_speed

    screen.fill((0, 0, 0))
    pygame.draw.rect(screen, (0, 255, 0), rect1)
    pygame.draw.rect(screen, (0, 255, 0), rect2)
    pygame.draw.rect(screen, (255, 255, 255), (player_x, player_y, 30, 50))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Ссылка: код-репозиторий упоминался в оригинале (MIT), используйте свой репозиторий для хранения примеров и тестов.

скроллинг простая игра с игроком и платформой

2. Несколько слоёв фона: параллакс простым способом

Для параллакса создайте несколько слоёв фона (прямоугольников) и задайте каждой разную скорость. Чем дальше слой — тем медленнее он движется. Это создаёт ощущение глубины.

Пример инициализации слоёв:

# Добавьте этот код после настройки экрана
background_layers = [
    pygame.Rect(0, 0, screen_width, screen_height),
    pygame.Rect(0, 0, screen_width, screen_height)
]

background_colors = [(30, 30, 30), (60, 60, 60)]
background_speeds = [0.1, 1.0]

Каждый элемент background_layers покрывает весь экран. background_speeds определяет относительную скорость слоя.

3. Обновление и отрисовка прокручивающегося фона

Обновляйте координаты слоёв в игровом цикле — смещайте по оси X на значение скорости. Когда слой вышел за левый край, возвращайте его в исходное положение, чтобы создать бесконечный цикл.

# Внутри игрового цикла
for i in range(len(background_layers)):
    background_layers[i].x -= background_speeds[i]

    if background_layers[i].x <= -screen_width:
        background_layers[i].x = 0

    pygame.draw.rect(screen, background_colors[i], background_layers[i])

Обратите внимание: использование вещественных скоростей (например, 0.1) потребует аккуратной работы с позициями: pygame.Rect хранит целочисленные координаты, поэтому при очень маленьких смещениях стоит хранить отдельный float-офсет и присваивать целочисленное значение rect.x при отрисовке.

игра с игроком, платформой и прокручивающимся фоном

4. Параллакс, зависящий от движения игрока

Чтобы усилить ощущение глубины, двигайте платформы и фоны относительно игрока: когда игрок двигается — за ним сдвигаются слои или платформы. Это особенно полезно в сайд-скроллерах.

Пример, где платформы представлены словарями с rect и speed:

# Определение платформ
rect1 = pygame.Rect(50, screen_height - 100, 200, 10)
rect2 = pygame.Rect(screen_width - 250, screen_height - 200, 200, 10)

platforms = [
    {"rect": rect1, "speed": 3},
    {"rect": rect2, "speed": 1}
]

# Внутри игрового цикла
keys = pygame.key.get_pressed()

if keys[pygame.K_LEFT] and player_x > 0:
    player_x -= player_speed
    for platform in platforms:
        platform["rect"].x -= platform["speed"]

if keys[pygame.K_RIGHT] and player_x < screen_width:
    player_x += player_speed
    for platform in platforms:
        platform["rect"].x += platform["speed"]

for platform in platforms:
    pygame.draw.rect(screen, (0, 255, 0), platform["rect"])

Такой подход включает прокрутку только при движении игрока, делая эффект более выразительным.

5. Дополнительные возможности

Ниже — набор простых улучшений, которые легко интегрировать.

Случайные цвета фонов

Меняйте цвета слоёв случайно, чтобы добавить вариативности при запуске.

import random

background_colors = [
    (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)),
    (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)),
    (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
]

Дополнительные слои

Добавление большего количества слоёв делает параллакс богаче. Пропорции скоростей должны быть последовательными: дальние слои — медленнее, ближние — быстрее.

background_layers = [
    pygame.Rect(0, 0, screen_width, screen_height),
    pygame.Rect(0, 0, screen_width, screen_height),
    pygame.Rect(0, 0, screen_width, screen_height),
    pygame.Rect(0, 0, screen_width, screen_height)
]

background_colors = [
    (30, 30, 30),
    (60, 60, 60),
    (90, 90, 90),
    (120, 120, 120)
]

background_speeds = [1, 2, 3, 4]

Использование изображений вместо цветов

Изображения дают богатые и детализированные фоны. Загрузите их, выполните convert() для ускорения и масштабируйте под экран.

# До начала игрового цикла
background_images = [
    pygame.image.load("background_0.png").convert(),
    pygame.image.load("background_1.png").convert(),
    pygame.image.load("background_2.png").convert()
]

background_speeds = [1, 2, 3]

for i in range(len(background_images)):
    size = (screen_width, screen_height)
    background_images[i] = pygame.transform.scale(background_images[i], size)

Для отрисовки используйте blit вместо draw.rect:

# Внутри игрового цикла
for i in range(len(background_layers)):
    background_layers[i].x -= background_speeds[i]

    if background_layers[i].x <= -screen_width:
        background_layers[i].x = 0

    screen.blit(background_images[i], background_layers[i])

Если вы используете изображения, рассмотрите приёмы тайлинга (повторения) по оси X и Y, чтобы избежать заметных швов.

6. Лучшие практики и оптимизация

Оптимизируйте только где нужно

Профилируйте игру — прежде чем оптимизировать, найдите узкие места. Для большинства 2D-игр узким местом чаще всего является частая перезагрузка/скейлинг больших изображений.

Используйте convert() и кэшируйте

Вызов surface.convert() или convert_alpha() снижает затраты на blit. Кэшируйте масштабированные версии изображений под целевые разрешения.

Минимизируйте перерисовку

При возможности перерисовывайте только те области экрана, которые изменились (dirty rects). Однако для полного экрана с параллаксом часто проще обновлять весь экран и держать частоту кадров стабильной.

Управление вещественными смещениями

Храните смещение слоя в отдельной float-переменной (например, offset_x) и преобразуйте в int для rect.x:

layer_offset = 0.0
layer_offset -= 0.1
background_layers[0].x = int(layer_offset)

Память и форматы

Сжимаемые форматы а-ля PNG хороши для качества, JPEG — для снимков без альфа. Следите за использованием памяти при множестве больших текстур.

Тестирование на разных разрешениях

Реализуйте масштабирование или отдельные наборы фоновых изображений для популярных аспектов (4:3, 16:9, 21:9).

7. Когда прокрутка не подходит (контр-примеры)

  • Не требуется в статических пазлах или минималистичных UI: лишнее движение отвлекает игрока.
  • Когда фон должен быть читабельным (например, карта с мелким текстом): прокрутка ухудшит читаемость.
  • На слабых устройствах при большом количестве высоких разрешений изображений — стоит отказаться или упростить эффект.

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

  • Tile-based (тайловая) прокрутка: хорошо для платформеров с большим миром.
  • Шейдерный параллакс (в OpenGL/SDL): более гибкий и эффективный на GPU.
  • Скелетная/слойная композиция: комбинируйте спрайты и эффекты вместо глобального смещения.

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

  • “Чем дальше от камеры — тем медленнее движется” — базовое правило параллакса.
  • Поддерживайте относительную скорость слоёв в стабильной пропорции 1 : 0.5 : 0.25 …
  • Если производительность падает на 60 FPS, снижайте разрешение фонов или уменьшайте количество слоёв.

10. Чек-лист перед выпуском

  • Проверить масштабирование фонов на 3–4 разрешениях
  • Прогнать профайлер: рендер → memory → CPU
  • Кэшировать все масштабированные изображения
  • Обеспечить fallback: упрощённый фон для слабых устройств
  • Убедиться в отсутствии визуальных швов при тайлинге

11. Мини-методология внедрения (SOP)

  1. Прототип: быстрые прямоугольные слои, три скорости.
  2. Тест: проверьте плавность и восприятие глубины.
  3. Итерация: добавьте графику вместо цвета, кэшируйте и оптимизируйте.
  4. Тестирование на устройствах и обратная связь.
  5. Релиз с опцией «низкое качество фона».

12. Шпаргалка (cheat sheet)

  • Для быстрой прокрутки используйте int скорости > 1;
  • Для тонкого параллакса используйте float-скорости и храните offset в float;
  • convert() = быстрее blit; convert_alpha() = сохраняет альфа;
  • При тайлинге: используйте две копии изображения и циклический сдвиг, чтобы избежать «провалов».

13. Пример решения проблемы швов при тайлинге

Если видно швы между повторяющимися изображениями, попробуйте:

  • Сгладить края изображений в редакторе;
  • Добавить небольшой overlapping (наложение) при blit, затем обрезать;
  • Использовать seamless-тайлы (в редакторе подготовить текстуру).

14. Дерево решений: как выбрать тип фона

flowchart TD
  A[Нужен фон для сцены?] -->|Да| B{Требуется ли высокая детализация?}
  B -->|Да| C[Использовать изображения 'png/jpeg']
  B -->|Нет| D[Использовать цветовые слои / градиенты]
  C --> E{Требуется параллакс?}
  E -->|Да| F[Несколько масштабированных слоёв с разными скоростями]
  E -->|Нет| G[Статический фон с витальностью]
  D --> H{Производительность важна?}
  H -->|Да| I[Минимизировать слои, использовать solid fills]
  H -->|Нет| F

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

  • Фон плавно двигается на целевой частоте кадров (обычно 60 FPS);
  • При масштабировании не теряется важная визуальная информация;
  • Нет визуальных швов или скачков при бесконечной прокрутке;
  • На слабых устройствах есть опция «низкое качество фона».

16. Роли и обязанности (короткий план)

  • Геймдизайнер: определяет желаемую глубину и художественный стиль;
  • Художник: готовит seamless-текстуры и вариативные слои;
  • Программист: реализует прокрутку, оптимизацию и fallback-сценарии;
  • QA: тестирует на наборе устройств и фиксирует баги с производительностью.

Итог

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

Внедряйте параллакс поэтапно: прототип → тест → оптимизация → релиз. Это позволит сохранить ясность архитектуры и обеспечить хороший пользовательский опыт.


Краткое резюме доступно в начале статьи. Если хотите — могу подготовить готовые файлы simple-game.py, scrolling-bg.py и parallax.py на базе примеров выше и снабдить их комментариями для запуска.

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

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

Как экономить мобильные данные в Apple Music
Мобильные данные

Как экономить мобильные данные в Apple Music

Персональные результаты Google Assistant на блокировке
Android.

Персональные результаты Google Assistant на блокировке

Настройка уведомлений Outlook: отключить и адаптировать
Справка

Настройка уведомлений Outlook: отключить и адаптировать

Добавить дату и время в Google Sheets
Электронные таблицы

Добавить дату и время в Google Sheets

Таймер Помодоро на Python с Tkinter
Python

Таймер Помодоро на Python с Tkinter

Как отключить 5G на Android — Samsung и Pixel
Android.

Как отключить 5G на Android — Samsung и Pixel