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

Враги в играх на Python с библиотекой Arcade — практическое руководство

5 min read Разработка игр Обновлено 03 Jan 2026
Враги в играх на Python (Arcade) — руководство
Враги в играх на Python (Arcade) — руководство

Стена с постером врага в игровом окружении

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

Создайте простую игру

Перед началом убедитесь, что на вашем устройстве установлен pip. Установите библиотеку Arcade командой:

pip install arcade

Далее создайте простую игру, где игрок может передвигаться влево и вправо стрелками. Ниже — минимальный рабочий пример окна и движения игрока.

import arcade  
  
# Window dimensions  
SCREEN_WIDTH = 800  
SCREEN_HEIGHT = 600  
  
# Player attributes  
PLAYER_RADIUS = 25  
PLAYER_SPEED = 5  
  
class GameWindow(arcade.Window):  
    def __init__(self, width, height):  
        super().__init__(width, height)  
        arcade.set_background_color(arcade.color.WHITE)  
        self.player_x = width // 2  
  
    def on_draw(self):  
        arcade.start_render()  
        arcade.draw_circle_filled(self.player_x, PLAYER_RADIUS, PLAYER_RADIUS, arcade.color.BLUE)  
  
    def on_key_press(self, key, modifiers):  
        if key == arcade.key.LEFT:  
            self.player_x -= PLAYER_SPEED  
        elif key == arcade.key.RIGHT:  
            self.player_x += PLAYER_SPEED  
  
    def update(self, delta_time):  
        pass  
  
def main():  
    window = GameWindow(SCREEN_WIDTH, SCREEN_HEIGHT)  
    arcade.run()  
  
if __name__ == "__main__":  
    main()

Код в статье хранится в репозитории GitHub и доступен по MIT‑лицензии — вы можете его использовать и модифицировать.

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

Чтобы сделать врага, достаточно отрисовать ещё один круг (или спрайт) и проверять пересечение с игроком. В простейшем случае при столкновении можно объявлять «Game Over». Ниже — пример добавления статичного врага и функции проверки столкновений.

# Add to GameWindow class  
  
class GameWindow(arcade.Window):  
    # ...  
  
    def __init__(self, width, height):  
        # ...  
  
        # Enemy attributes  
        self.enemy_x = width // 2  
        self.enemy_y = height - PLAYER_RADIUS  
        self.enemy_radius = 20  
  
    def on_draw(self):  
        # ...  
        arcade.draw_circle_filled(self.enemy_x, self.enemy_y, self.enemy_radius, arcade.color.RED)  
  
    def update(self, delta_time):  
        if self.is_collision(self.player_x, self.player_y, self.enemy_x, self.enemy_y, PLAYER_RADIUS, self.enemy_radius):  
            print("Game Over!")  
      
    def is_collision(self, x1, y1, x2, y2, radius1, radius2):  
        distance_squared = (x1 - x2)  2 + (y1 - y2)  2  
        radius_sum_squared = (radius1 + radius2)  2  
        return distance_squared <= radius_sum_squared

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

Преследование игрока

Интересный элемент геймплея — враг, который преследует игрока. Это добавляет динамики и заставляет игрока маневрировать. Подсказка: для простоты обновляйте координату врага на каждой итерации update в направлении игрока. Создайте файл enemy-follow-player.py и примените логику ниже.

# Add to GameWindow class  
  
class GameWindow(arcade.Window):  
    # ...  
  
    def update(self, delta_time):  
        if self.player_x < self.enemy_x:  
            self.enemy_x -= PLAYER_SPEED  
        elif self.player_x > self.enemy_x:  
            self.enemy_x += PLAYER_SPEED  
  
        if self.is_collision(self.player_x, self.player_y,  
                            self.enemy_x, self.enemy_y,  
                            PLAYER_RADIUS, ENEMY_RADIUS):  
           print("Game Over!")  
  
    def is_collision(self, x1, y1, x2, y2, radius1, radius2):  
        distance_squared = (x1 - x2)  2 + (y1 - y2)  2  
        radius_sum_squared = (radius1 + radius2)  2  
        return distance_squared <= radius_sum_squared

Ниже — визуализация поведения:

Враг преследует игрока в демонстрации Arcade

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

Пули от врага

Чтобы враг мог стрелять, добавьте класс Bullet и список активных пуль. Враг периодически создаёт новые пули, которые затем двигаются по сцене. Создайте файл bullets.py и добавьте следующий код:

# Add to GameWindow class  
  
class Bullet:  
    def __init__(self, x, y, radius, speed):  
        self.x = x  
        self.y = y  
        self.radius = radius  
        self.speed = speed  
  
    def update(self):  
        self.y -= self.speed  
  
class GameWindow(arcade.Window):  
    # ...  
  
    def __init__(self, width, height):  
        # ...  
  
        # Enemy attributes  
        self.bullets = []  
        self.bullet_radius = 5  
        self.bullet_speed = 3  
        self.bullet_cooldown = 60# Number of frames between bullet spawns  
        self.bullet_timer = 0  
  
    def on_draw(self):  
        # ...  
        for bullet in self.bullets:  
            arcade.draw_circle_filled(bullet.x, bullet.y,   
           self.bullet_radius, arcade.color.BLACK)  
  
    def update(self, delta_time):  
        # ...  
  
        self.bullet_timer += 1  
        if self.bullet_timer >= self.bullet_cooldown:  
            self.bullets.append(Bullet(self.enemy_x, self.enemy_y - self.enemy_radius,   
self.bullet_radius, self.bullet_speed))  
            self.bullet_timer = 0  
  
        for bullet in self.bullets:  
            bullet.update()  
            if self.is_collision(self.player_x, self.player_y, self.enemy_x,   
self.enemy_y, PLAYER_RADIUS, ENEMY_RADIUS):  
            print("Game Over!")  
      
    def is_collision(self, x1, y1, x2, y2, radius1, radius2):  
        distance_squared = (x1 - x2)  2 + (y1 - y2)  2  
        radius_sum_squared = (radius1 + radius2) ** 2  
        return distance_squared <= radius_sum_squared

Враг стреляет пулями по игроку в демонстрации

Примечание: в реальной игре нужно аккуратно убирать пули, вышедшие за пределы экрана, чтобы не накапливать объекты и не утяжелять память.

Очки здоровья для врагов

Чтобы враги могли выдерживать несколько ударов, добавьте им параметр здоровья (HP). Это открывает возможности для стратегий и ощущения прогресса. В примере ниже задаётся константа ENEMY_HEALTH и уменьшается при столкновениях.

# Window dimensions  
SCREEN_WIDTH = 800  
SCREEN_HEIGHT = 600  
  
# Player attributes  
PLAYER_RADIUS = 25  
PLAYER_SPEED = 5  
  
# Enemy attributes  
ENEMY_RADIUS = 20  
ENEMY_HEALTH = 100  
  
class GameWindow(arcade.Window):  
    def __init__(self, width, height):  
        super().__init__(width, height)  
        arcade.set_background_color(arcade.color.WHITE)  
        self.player_x = width // 2  
        self.player_y = height // 2  
        self.enemy_x = width // 2  
        self.enemy_y = height - PLAYER_RADIUS  
        self.enemy_health = ENEMY_HEALTH  
        print(self.enemy_health)  
    def on_draw(self):  
        arcade.start_render()  
        arcade.draw_circle_filled(self.player_x,  
                                  self.player_y,  
                                  PLAYER_RADIUS,  
                                  arcade.color.BLUE)  
        if self.enemy_health > 0:  
            arcade.draw_circle_filled(self.enemy_x,  
                                      self.enemy_y,  
                                      ENEMY_RADIUS,  
                                      arcade.color.RED)  
  
    def update(self, delta_time):  
        if self.is_collision(self.player_x, self.player_y,  
                             self.enemy_x, self.enemy_y,  
                             PLAYER_RADIUS, ENEMY_RADIUS):  
            self.enemy_health -= 10  
            print(self.enemy_health)  

Вы можете отрисовать полоску здоровья (health bar) над врагом или выводить текстовую метку с текущим HP для наглядности.

Рекомендации по созданию врагов

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

Разнообразные атрибуты

Давайте у врагов разные параметры: скорость, размер, здоровье, урон. Это позволяет создавать уровни с растущей сложностью и вынуждает игрока менять тактику.

Уникальные поведения

Некоторые враги могут двигаться предсказуемо, другие — хаотично. Можно использовать простые состоянья: патруль, преследование, уклонение. Для сложного поведения подойдёт поведенческое дерево или конечный автомат.

Очки здоровья (HP)

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

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

Когда такой подход не подходит

  • Массовые враги: если у вас сотни врагов, индивидуальные проверки столкновений и частые обновления приведут к просадкам FPS; используйте пространственные структуры (кубы/клетки, quad-tree) или физические движки.
  • Сложная физика: если требуется столкновение по полигонам, отскоки, силы, используйте Pymunk/Box2D вместо ручных круговых коллизий.
  • Сетевая игра: поведение на клиенте/сервере нужно синхронизировать и защищать от читов — авторитетность на сервере.

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

  • Спрайты Arcade: используйте arcade.Sprite и arcade.SpriteList для автоматической батчевой отрисовки и встроенных способов проверки коллизий.
  • Физические движки: Pymunk для точной физики с угловой скоростью и столкновениями.
  • Поведенческие деревья / FSM: для сложной логики ИИ.

Мини‑методология для добавления нового типа врага

  1. Определите роль врага (нагнетатель, пушер, миньон, босс).
  2. Задайте базовые параметры: скорость, размер, HP, урон, радиус коллизии.
  3. Реализуйте визуал и спрайт(ы).
  4. Напишите update() с простым поведением.
  5. Добавьте тесты: столкновения, смерть, производительность.
  6. Итеративно балансируйте на реальном уровне.

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

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

    • Коллизии работают корректно на разных разрешениях.
    • Пули очищаются после выхода с экрана.
    • Нет утечек объектов при уничтожении врагов.
    • Есть логирование ошибок.
  • Дизайнер:

    • Поведение врага очевидно игроку (аудио/визуальная обратная связь).
    • Параметры сложности протестированы.
    • Враги вписываются в визуальный стиль.
  • QA:

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

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

  • Враг отображается и двигается согласно логике.
  • Столкновения детектируются при пересечении радиусов.
  • Пули от врага наносят урон/срабатывают и удаляются корректно.
  • Очки здоровья уменьшаются и влияют на отображение (health bar или текст).
  • Производительность не падает при целевой нагрузке (см. требования проекта).

Факт‑бокс: ключевые числа из примеров

  • Разрешение окна: 800×600 пикселей.
  • Радиус игрока: 25.
  • Скорость игрока: 5 (пикселей/обновление).
  • Радиус врага: 20.
  • HP врага (по умолчанию): 100.
  • Параметры пуль: radius=5, speed=3, cooldown=60 кадров.

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

Добавление врагов — это не только отрисовка и проверка коллизий. Хорошо спроектированный враг имеет четкую роль, поведенческую модель и управляемые параметры. Используйте спрайты и списки объектов для производительности, выносите параметры в константы и тестируйте изменения в реальном геймплее.

Если вы хотите, можно адаптировать примеры к спрайтам arcade.Sprite, добавить полоски HP и реализовать поведение через FSM — напишите, какой вариант вам интересен, и я подготовлю доработанный пример с пояснениями.

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

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

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство