Простой ИИ врагов

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

Слово «ИИ» звучит пугающе, но в 2D-играх это почти всегда простые правила, а не нейросети. Враг, который ходит туда-сюда; враг, который бежит за игроком; враг, который стреляет, когда ты близко — всё это десяток строк обычной логики. И вся она прекрасно проверяется без графики, ведь это снова чистая математика направлений и расстояний.

Самый простой ИИ — патруль: враг ходит между двумя точками, разворачиваясь у краёв. Чуть умнее — преследование: каждый кадр враг считает вектор к игроку (как мы делали с мышью) и движется по нему. Ещё умнее — поведение по расстоянию: если игрок далеко, враг патрулирует; если приблизился — начинает гнаться; если совсем рядом — атакует. Это уже простая машина состояний для одного врага.

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

Как работает под капотом

Враг измеряет дистанцию до игрока и по порогам выбирает поведение:

        дистанция до игрока
   далеко       средне        близко
   |------------|-------------|----------|
   ПАТРУЛЬ      ПРЕСЛЕДОВАНИЕ   АТАКА
   ходит        бежит к         стреляет
   туда-сюда    игроку          в игрока

   dist = sqrt((px-ex)^2 + (py-ey)^2)

В pygame враг-преследователь (читаем):

class Chaser(pygame.sprite.Sprite):
    def update(self, dt, player_pos):
        to_player = pygame.math.Vector2(player_pos) - self.pos
        dist = to_player.length()
        if dist < 300 and dist > 0:
            self.pos += to_player.normalize() * self.speed * dt
        self.rect.center = (round(self.pos.x), round(self.pos.y))

Логику выбора поведения врага проверим полностью без графики. Запусти и посмотри, как враг меняет режим по дистанции. Попробуй сам:

import math

def enemy_behavior(enemy, player, attack_r=80, chase_r=250):
    dist = math.hypot(player[0]-enemy[0], player[1]-enemy[1])
    if dist <= attack_r:
        return f"АТАКА (dist={dist:.0f})"
    elif dist <= chase_r:
        return f"ПРЕСЛЕДОВАНИЕ (dist={dist:.0f})"
    else:
        return f"ПАТРУЛЬ (dist={dist:.0f})"

enemy = (400, 300)
for player in [(420, 320), (550, 350), (700, 300)]:
    print(enemy_behavior(enemy, player))

Конечный автомат для одного врага

Заметь красивую симметрию: машина состояний, которой мы управляли экранами игры, точно так же управляет поведением одного врага. У врага есть состояния — «патруль», «погоня», «атака», «отступление» — и переходы между ними по условиям (увидел игрока, потерял из виду, мало здоровья). Это называется конечным автоматом поведения (behavior FSM), и это рабочая лошадка ИИ в играх от аркад до больших проектов. Никаких нейросетей — только понятные состояния и правила перехода.

Расширять такой ИИ легко и приятно. Добавь состояние «бегство», в которое враг уходит при низком здоровье, и он начнёт удирать от игрока — тот же вектор направления, только со знаком минус. Добавь «поиск», когда враг потерял игрока из виду и идёт к последней замеченной точке, — и противник станет ощущаться сообразительным. Каждое новое состояние — это десяток строк понятной логики, проверяемой без графики, как в запускаемом примере. Так из простых кирпичиков собирается враг, который кажется живым и думающим, хотя внутри это всего лишь аккуратные if-правила.

Частые ошибки

  • Нормализовать вектор к игроку без проверки длины — если враг точно на игроке, деление на ноль.
  • Жёсткие пороги без «зоны спокойствия» — враг дёргается между режимами на границе. Делай пороги входа и выхода разными.
  • Забыть dt у движения врага — скорость поедет от FPS.

Best practices

  • Описывай ИИ порогами расстояния — легко настраивать сложность.
  • Для плавности используй гистерезис: входить в погоню на 250, выходить на 300.
  • Сложное поведение собирай из простых режимов — мини-машина состояний на врага.

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

Проверьте себя
1. На чём чаще всего строится простой ИI врага в 2D-игре?
AНа нейросети
BНа правилах с порогами расстояния до игрока
CНа случайных числах без правил
DНа звуковых эффектах
2. Зачем разносить пороги входа и выхода из режима погони (гистерезис)?
AЧтобы было быстрее
BЧтобы враг не дёргался между режимами на границе расстояния
CЧтобы включить звук
DЧтобы враг исчез