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

Враги в PyGame: движения и поведение

4 min read Разработка игр Обновлено 17 Dec 2025
Враги в PyGame: движения и поведение
Враги в PyGame: движения и поведение

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

Игрок контролирует персонажа на экране ПК

Одним из важнейших элементов хорошей видеоигры являются враги. Это могут быть зомби, инопланетяне или другие игроки: враги делают игру сложнее и интереснее.

В PyGame легко запрограммировать разные типы поведения врагов: преследование игрока, случайное движение, следование по путям и другие.

Создание простой игры

Начнем с простой игры: игрок двигается горизонтально и вертикально. Если игрок касается врага — игра заканчивается.

Полный код можно положить в репозиторий на GitHub для удобного доступа и версионирования.

Начните с импорта PyGame и инициализации:

import pygame

pygame.init()

Далее настроим окно и создадим объекты игрока и врага с помощью pygame.Rect():

# Настройка экрана
screen = pygame.display.set_mode((800, 600))

# Цвета
black = (0, 0, 0)
white = (255, 255, 255)

# Игрок и враг как прямоугольники
player = pygame.Rect(350, 500, 50, 50)
enemy = pygame.Rect(350, 0, 50, 50)

Создайте игровой цикл, который работает, пока игрок не столкнется с врагом или не закроет окно. Проверяйте коллизии и рисуйте объекты:

# Игровой цикл
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Заполнить экран
    screen.fill(white)

    # Движение игрока
    keys = pygame.key.get_pressed()

    if keys[pygame.K_LEFT]:
        player.x -= 5
    if keys[pygame.K_RIGHT]:
        player.x += 5
    if keys[pygame.K_UP]:
        player.y -= 5
    if keys[pygame.K_DOWN]:
        player.y += 5

    # Проверка коллизии
    if player.colliderect(enemy):
        running = False

    # Рисуем игрока и врага
    pygame.draw.rect(screen, black, player)
    pygame.draw.rect(screen, black, enemy)

    # Обновляем экран
    pygame.display.update()

# Завершение
pygame.quit()

Важно: соблюдайте границы экрана (ограничивайте координаты), чтобы объекты не ушли за пределы окна.

Направить врага к игроку

Чтобы враг шел к игроку, вычислите расстояние между ними (по теореме Пифагора). На основе этого расстояния задайте направление и нормализуйте вектор движения.

# Вычисление расстояния
distance_x = player.x - enemy.x
distance_y = player.y - enemy.y
distance = (distance_x  2 + distance_y  2) ** 0.5

# Скорость врага
speed = 2

if distance != 0:
    enemy.x += speed * distance_x / distance
    enemy.y += speed * distance_y / distance

Замечание: при малых расстояниях нормализация защищает от деления на ноль.

Случайное движение врага

Чтобы враг двигался случайно, используйте модуль random и выбирайте направление из списка вариантов.

import random

# Случайное направление
direction = random.choice(['left', 'right', 'up', 'down'])

if direction == 'left':
    enemy.x -= 5
elif direction == 'right':
    enemy.x += 5
elif direction == 'up':
    enemy.y -= 5
elif direction == 'down':
    enemy.y += 5

Совет: добавьте вероятность смены направления и таймер, чтобы движение выглядело плавнее.

Движение при близости

Можно сделать так, чтобы враг активировался только при приближении игрока. Это экономит ресурсы и добавляет тактический слой.

# Скорость и радиус активации
speed = 2
activation_radius = 300

if distance < activation_radius:
    if distance != 0:
        enemy.x += speed * distance_x / distance
        enemy.y += speed * distance_y / distance

Примечание: радиус активации настраивается под механику уровня.

Увертывание от атаки игрока

Враг может уклоняться, двигаясь перпендикулярно вектору к игроку. Для этого вычисляем единичный вектор к игроку и его перпендикуляр.

speed = 2

action_radius = 400

if distance < action_radius:
    if distance != 0:
        # Единичный вектор к игроку
        unit_vector_x = distance_x / distance
        unit_vector_y = distance_y / distance

        # Перпендикулярный вектор
        perpendicular_vector_x = -unit_vector_y
        perpendicular_vector_y = unit_vector_x

        # Скалярное произведение
        dot_product = (perpendicular_vector_x * unit_vector_x
                       + perpendicular_vector_y * unit_vector_y)

        # Движение перпендикулярно
        if dot_product > 0:
            enemy.x += speed * perpendicular_vector_x
            enemy.y += speed * perpendicular_vector_y
        else:
            enemy.x -= speed * perpendicular_vector_x
            enemy.y -= speed * perpendicular_vector_y

Так враг избегает прямого столкновения и усложняет поведение.

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

Добавьте несколько врагов, препятствия, усиления и контролируемую частоту кадров через Clock:

import random
import pygame

# Несколько врагов
enemies = []
for i in range(5):
    enemy = pygame.Rect(random.randint(0, 750), random.randint(0, 550), 50, 50)
    enemies.append(enemy)

# Препятствие
obstacle = pygame.Rect(200, 250, 50, 50)

# Игровой цикл с FPS
clock = pygame.time.Clock()
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill(white)

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= 5
    if keys[pygame.K_RIGHT]:
        player.x += 5
    if keys[pygame.K_UP]:
        player.y -= 5
    if keys[pygame.K_DOWN]:
        player.y += 5

    for enemy in enemies:
        direction = random.choice(['left', 'right', 'up', 'down'])
        if direction == 'left':
            enemy.x -= 5
        elif direction == 'right':
            enemy.x += 5
        elif direction == 'up':
            enemy.y -= 5
        elif direction == 'down':
            enemy.y += 5

        if player.colliderect(enemy):
            running = False

    pygame.draw.rect(screen, black, player)
    for enemy in enemies:
        pygame.draw.rect(screen, black, enemy)
    pygame.draw.rect(screen, black, obstacle)

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

pygame.quit()

Методология разработки поведения врагов (мини-метод)

  1. Определите цель врага: преследовать, патрулировать, уклоняться или поддерживать дистанцию.
  2. Выберите базовое движение: вектор к игроку, случайный выбор, путь по waypoints.
  3. Нормализуйте вектор движения, задайте скорость и добавьте вариативность (прыжки, задержки).
  4. Обработайте коллизии и границы экрана.
  5. Протестируйте поведение в разных сценариях и отладьте параметры.

Когда эти подходы не подходят

  • Большие уровни с миллионами объектов: простая обработка каждого врага нагрузит CPU. Решение: LOD, активация по дистанции или патче обновлений.
  • Сложные физические взаимодействия: PyGame не заменит полноценный физический движок. Решение: интегрировать Box2D или pymunk.
  • Сетевые игры с синхронизацией: предикция и компенсация задержек потребуют отдельной логики.

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

  • Поведение на основе состояний (State Machine): для сложных ИИ используйте состояния: «патруль», «преследование», «уход».
  • Навигационные сетки (navmesh) и поиск пути (A*): для уровней с препятствиями.
  • Поведение на основе правил или деревьев решений (behaviour trees) для гибкости и расширяемости.

Чек-лист для роли разработчика и тестировщика

Для разработчика:

  • Нормализован вектор движения
  • Обработаны границы экрана
  • Добавлены таймеры для смены направления
  • Коллизии корректны

Для тестировщика:

  • Враг активируется только в радиусе
  • Враг не застревает в препятствиях
  • Поведение в группах не вызывает накладок
  • ФПС стабильный при множестве врагов

Кейсы тестирования и критерии приёмки

  1. Пересечение: при касании врага игра завершается — приемка: игра прекращается и показывается экран поражения.
  2. Преследование: при появлении игрока в радиусе враг корректно идет к игроку.
  3. Случайность: враги меняют направление с заданной частотой и не телепортируются.
  4. Увертывание: при приближении на заданную дистанцию враг корректно уходит в сторону.

Полезный шпаргалка — скорость и дистанции

  • Скорость базового преследования: 1–4 пикселя/кадр (настраивается).
  • Радиус активации: 200–400 пикселей для окна 800×600.
  • Частота смены направления для случайного движения: 0.5–2 секунды.

Советы по оптимизации

  • Обновляйте поведение врагов реже, если их много (например, раз в 2–4 кадра).
  • Включайте поведение только для врагов в видимой области или в радиусе активации.
  • Используйте простые примитивы (Rect) для коллизий, а не сложные полигоны.

Итог

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

Важно: тестируйте в разных ситуациях и адаптируйте параметры под конкретную механику уровня.

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

  • Враги делают игру интереснее.
  • Базовые подходы: преследование, случайное движение, активация по дистанции, уклонение.
  • Для сложного ИИ используйте state machine, A* или behaviour trees.

Примечание: полный пример кода удобно хранить в репозитории на GitHub для совместной работы и дальнейшего расширения.

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

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

Как импортировать закладки в Firefox
Браузеры

Как импортировать закладки в Firefox

DuckDuckGo для Windows — бета‑браузер приватности
Браузеры

DuckDuckGo для Windows — бета‑браузер приватности

Кастомная RSS‑лента с Zapier и альтернативы
Инструменты

Кастомная RSS‑лента с Zapier и альтернативы

Не вставляются числа в калькулятор Windows 11 — решение
Windows

Не вставляются числа в калькулятор Windows 11 — решение

Как собрать игровой ПК — пошаговое руководство
Сборка ПК

Как собрать игровой ПК — пошаговое руководство

Как подписать документ онлайн — сервисы и инструкции
Productivity

Как подписать документ онлайн — сервисы и инструкции