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