Интеллект своими руками!

Раздел: Для новичков.

Автор: БигБум.

Подобный вариант ИИ используется в проекте Clan Wars.

Делать искусственный интеллект любому программисту на Game Maker когда-нибудь придётся. Конечно, клепать тетрисы и игры наподобие Lines просто и интересно. Но когда-то любому игроделу захочется сделать игру, в которой кроме игрока есть ещё и NPC (Non-Player Character). Тут на помощь придёт данное руководство.

Вариант ИИ, рассматриваемый в данном руководстве, предназначен для игр с видом сверху, хотя есть шанс, что кое-что из этого руководства пригодится вам и в других проектах.

Начнём!

Начинать создание ИИ мы, естественно, будем с создания игровых объектов. Что нам понадобится?

Во-первых, создадим объект игрока (я назвал его obj_player). Кроме того, нам понадобятся объект NPC (obj_enemy) и объект блока, который наш ИИ будет обходить (obj_block). Не забудьте поставить спрайты для всех этих объектов!

Это легко.

Для начала определимся, что должен делать наш враг. Было бы глупо делать так, чтобы ИИ постоянно преследовал нашего героя. Поэтому он будет преследовать нашего героя только в том случае, если видит его. На приведённом ниже рисунке враг стоит на месте, так как не видит нашего игрока.

Как же сделать, чтобы NPC двигался только в том случае, если видит героя? Для этого вам очень пригодится функция collision_line.

[!] collision_line(x1, y1, x2, y2, obj, prec, notme) – функция проверяет, есть ли столкновение между линией сегмента из (x1, y1), в (x2, y2) и объектами obj. Вы можете использовать её для проверки - может ли образец объекта видеть другой образец объекта, заодно проверяя, пролегает ли линия сегмента между стеной.

НЕ нашли? Не то? Что вы ищете?

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

Для этого в событие Create каждого героя мы запишем следующее:

Sight=100*random(5);

Gotoplayer=0;

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

Вторая переменная Gotoplayer говорит за себя: если поставить эту переменную равной 1, то враг будет идти за игроком с самого начала игры, независимо от того, видит он его или нет.

Теперь нужно записать следующее в событие Step:

If distance_to_object(obj_player) < sight

{

If collision_line(x, y, obj_player. x, obj_player. y, obj_block, 0, 0)

{

Gotoplayer=1

}

}

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

Кстати, этот кусок кода можно записать иначе. Например, так:

If (distance_to_object(obj_player) < sight) and (collision_line(x, y, obj_player. x, obj_player. y, obj_block, 0, 0))

{

Gotoplayer=1

}

Теперь наш враг определяет, в каком случае нужно двигаться к игроку. Но он ещё не двигается. Впрочем, сейчас этот недочёт будет исправлен.

Напишем следующее в событии Step ниже предыдущего куска кода:

If Gotoplayer=1

{

direction=point_direction(x, y, obj_player. x, obj_player. y)

mp_potential_step(obj_player. x, obj_player. y, 4, 0)

}

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

Если скорость врага покажется слишком высокой, то можно заменить цифру 4 в функции mp_potential_speed на меньшую.

Всё!

Теперь можно запускать проект. Как вы видите, всё работает вполне нормально и стабильно. Конечно, есть несколько минусов, но всё это вы можете исправить, используя знания, накопившиеся в данном уроке.

Домашнее задание

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

Start_x=x

Start_y=y

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