Враги в 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()Методология разработки поведения врагов (мини-метод)
- Определите цель врага: преследовать, патрулировать, уклоняться или поддерживать дистанцию.
- Выберите базовое движение: вектор к игроку, случайный выбор, путь по waypoints.
- Нормализуйте вектор движения, задайте скорость и добавьте вариативность (прыжки, задержки).
- Обработайте коллизии и границы экрана.
- Протестируйте поведение в разных сценариях и отладьте параметры.
Когда эти подходы не подходят
- Большие уровни с миллионами объектов: простая обработка каждого врага нагрузит CPU. Решение: LOD, активация по дистанции или патче обновлений.
- Сложные физические взаимодействия: PyGame не заменит полноценный физический движок. Решение: интегрировать Box2D или pymunk.
- Сетевые игры с синхронизацией: предикция и компенсация задержек потребуют отдельной логики.
Альтернативные подходы
- Поведение на основе состояний (State Machine): для сложных ИИ используйте состояния: «патруль», «преследование», «уход».
- Навигационные сетки (navmesh) и поиск пути (A*): для уровней с препятствиями.
- Поведение на основе правил или деревьев решений (behaviour trees) для гибкости и расширяемости.
Чек-лист для роли разработчика и тестировщика
Для разработчика:
- Нормализован вектор движения
- Обработаны границы экрана
- Добавлены таймеры для смены направления
- Коллизии корректны
Для тестировщика:
- Враг активируется только в радиусе
- Враг не застревает в препятствиях
- Поведение в группах не вызывает накладок
- ФПС стабильный при множестве врагов
Кейсы тестирования и критерии приёмки
- Пересечение: при касании врага игра завершается — приемка: игра прекращается и показывается экран поражения.
- Преследование: при появлении игрока в радиусе враг корректно идет к игроку.
- Случайность: враги меняют направление с заданной частотой и не телепортируются.
- Увертывание: при приближении на заданную дистанцию враг корректно уходит в сторону.
Полезный шпаргалка — скорость и дистанции
- Скорость базового преследования: 1–4 пикселя/кадр (настраивается).
- Радиус активации: 200–400 пикселей для окна 800×600.
- Частота смены направления для случайного движения: 0.5–2 секунды.
Советы по оптимизации
- Обновляйте поведение врагов реже, если их много (например, раз в 2–4 кадра).
- Включайте поведение только для врагов в видимой области или в радиусе активации.
- Используйте простые примитивы (Rect) для коллизий, а не сложные полигоны.
Итог
Враги разнообразят геймплей и могут быть простой или сложной частью вашей игры. Начните с базовых паттернов: преследование, случайное движение, активация по близости, и затем усложняйте поведение с помощью состояний, поиска пути или поведения на основе дерева решений.
Важно: тестируйте в разных ситуациях и адаптируйте параметры под конкретную механику уровня.
Краткое резюме
- Враги делают игру интереснее.
- Базовые подходы: преследование, случайное движение, активация по дистанции, уклонение.
- Для сложного ИИ используйте state machine, A* или behaviour trees.
Примечание: полный пример кода удобно хранить в репозитории на GitHub для совместной работы и дальнейшего расширения.
Похожие материалы
Как импортировать закладки в Firefox
DuckDuckGo для Windows — бета‑браузер приватности
Кастомная RSS‑лента с Zapier и альтернативы
Не вставляются числа в калькулятор Windows 11 — решение
Как собрать игровой ПК — пошаговое руководство