Написание ИИ для хоккея. Часть 1
21К открытий21К показов
Существуют различные способы создать какую-нибудь особенную игру. Чаще всего разработчик для получения лучшего результата выбирает такую игру, которую он уже в состоянии написать. Сегодня мы попробуем прыгнуть выше наших голов — создадим искусственный интеллект для игры в хоккей!
Ключевым моментом будет использование рулевого поведения (steering behaviors), о котором я рассказывал в одной из своих прошлых статей (рассказ от лица автора — прим. переводчика).
Примечание Несмотря на то, что эти уроки написаны с использованием Action Script 3 и Flash, вам не должно составить труда реализовать игру в любой другой среде разработки на любом языке программирования.
Введение
Хоккей — одна из самых популярных спортивных игр. О нем написано множество статей, охватывающих и тактику игры, и поведение игроков в атаке и в защите, и такую тонкую вещь, как работа в команде. И, разумеется, искусственный интеллект. Реализация хоккея отлично подходит для демонстрации сочетания некоторых полезных приемов и методов.
Хоккей — динамичная игра. Если движения игроков будут предопределены, то играть в нее станет совсем скучно и неинтересно. Но как же нам создать динамичную игру, да при том, чтобы игроки вели себя адекватно и осознанно? Ответ прост — с помощью механики рулевого поведения.
Использование рулевого поведения направлено на создание реалистичных моделей передвижения объектов. Они основаны на простых силах, вследствие чего — чрезвычайно динамичны по своей природе. Это делает их идеальным выбором для реализации сложных и реалистичных движений, которые встречаются в футболе или в том же хоккее.
Обзор предстоящей работы
Как уже говорилось выше, хоккей — очень сложная игра. В ней присутствует огромное количество правил, нарушений и т.д. Для сокращения времени обучения, мы несколько упростим игру и сохраним лишь небольшой набор оригинальных правил этого вида спорта: у нас не будет вратарей (все игроки на катке будут двигаться), а также мы не будем учитывать всевозможные штрафы.
Так будет выглядеть наша игра
Ворота в нашей игре тоже будут своеобразные — сетка будет отсутствовать, а для того, чтобы забить гол, достаточно шайбе коснуться “ворот” с любой стороны. После забитого гола все игроки встают на свои позиции, шайба перемещается в центр, и через несколько секунд игра начинается заново.
Касаемо обработки шайбы: если игрок А находится с шайбой, а игрок B сталкивается с ним, то шайба переходит к игроку B, который становится недвижимым на некоторое время.
Для вывода графики я буду использовать графический движок Flixel. Однако в прилагаемом коде я буду опускать все связанное с графикой и максимально обращать ваше внимание на механику игры.
Базовые классы
Давайте начнем с основ — катка, который представляет собой прямоугольник, игроков и двух ворот. Каток имеет физические границы, поэтому ничего не выйдет за пределы поля. Хоккеист будет описываться классом Athlete
:
Поле mBoid
является объектом класса Boid
, более подробно о котором вы можете прочитать в серии уроков про рулевое поведение. Он имеет, среди прочих элементов, вектор направления, вектор силы, а также текущее положение игрока.
Метод update()
будет вызываться каждый раз, пока запущена игра. Сейчас в этом методе очищается любое активное усилие в рулевом поведении, добавляется эффект блуждания игрока, а также вызывается метод mBoid.update()
.
Класс, ответственный за саму игру, называется PlayState
. Среди его полей есть каток, две группы хоккеистов, а также двое ворот.
Если мы добавим одного хоккеиста на поле, то увидим такой результат:
Следуй за мышью
Мышь имеет координаты на экране, а потому мы можем использовать их в качестве пункта назначения для игрока. Мы можем использовать метод arrival
объекта mBoid
. Он задает цель, которую будет преследовать игрок. Движение будет плавным, а по мере приближения скорость хоккеиста будет падать и, в конце концов, станет равна 0.
Давайте заменим блуждающий метод в классе Athlete
на движение к курсору мыши:
В результате мы получим возможность управлять нашим игроком мышью, а движение получится плавным и реалистичным.
Добавим шайбу
Шайба будет описываться классом Puck
. Самое важное здесь — метод update()
и поле mOwner
.
Следуя той же логике, что и выше, метод update()
будет выполняться каждый раз, пока запущена игра. Поле mOwner
будет хранить того хоккеиста, который владеет шайбой. Если же mOwner
равно null
, то шайба никому не принадлежит и она свободно скользит по катку.
Если же mOwner
не равно null
, то владелец у шайбы имеется. В этом случае шайба насильно ставится перед своим владельцем. Для этого используется вектор скорости хоккеиста, который также соответствует и вектору направления. Вот наглядная иллюстрация:
Ставим шайбу перед ее владельцем
А вот и код:
В классе PlayState
есть проверка на коллизию с шайбой. Если какой-то хоккеист перекроет шайбу, то он становится новым владельцем. Вы можете протестировать это в демо-режиме, представленном ниже:
Удар по шайбе
Реализуем удар по шайбе клюшкой. Независимо от того, кто является владельцем шайбы, нам нужно сымитировать удар по ней и вычислить направление этого удара. Затем отправить шайбу по найденному вектору. Вычислить этот вектор несложно:
Вычисление вектора удара]
А вот и реализация удара по шайбе:
В классе PlayState
метод goFromStickHit()
выполняется каждый раз, когда игрок нажимаете на экран. Координата клика используется в качестве конечной точки для удара.
Добавление ИИ
До сих пор у нас был только один хоккеист на катке. Поскольку в хоккее по 6 человек на команду, а это уже целая дюжина игроков, то нам стоит задуматься о создании искусственного интеллекта для них. Да причем такого, чтобы игроки вели себя естественно и рационально.
Для этого мы будем использовать конечный автомат (FSM – finite state machine). Как было написано ранее, FSM является универсальным и полезным инструментом для реализации ИИ в играх.
Немного изменим наш класс Athlete
:
Поле mBrain
является экземпляром класса StackFSM
, о котором более подробно вы можете узнать из этой статьи. Он использует стек для управления состоянием ИИ. Каждое состояние описывается методом, и, когда состояние кладется в стек, оно становится активным и вызывается каждый раз при вызове основного метода update()
.
Все состояния игрока будут выполнять строго определенную функцию: взять шайбу, отобрать шайбу, патрулировать зону и т.д.
Теперь хоккеист может быть как под нашим контролем, так и под контролем ИИ. Обновим наш класс:
Если хоккеист находится под контролем искусственного интеллекта, то мы обновляем ее логику, вызывая mBrain.update()
. Если же хоккеист под управлением игрока, то логика ИИ игнорируется, а спортсмен следует за мышью.
Что касается самих состояний, посылаемых искусственному интеллекту, то мы реализуем два из них. Первое будет отвечать за подготовку игроков к матчу, т.е. они переместятся к своим стартовым позициям и будут смотреть на шайбу. Второе состояние просто будет заставлять хоккеиста стоять и следить за шайбой.
Состояние покоя
На данный момент это состояние будет активным всегда. Но в дальнейшем, оно заменит собой другие состояния, например, attack
.
Метод stopAndlookAt()
высчитывает нужное направление по тому же алгоритму, по которому мы вычисляли направление удара. Вектор, начинающийся с позиции хоккеиста и заканчивающийся позицией шайбы, измеряется по формуле thePoint - mBoid.position
и используется для указания направления взгляда спортсмена.
Если применить полученный вектор к хоккеисту, то он устремиться к шайбе. Для того, чтобы он оставался на месте, мы умножаем вектор на число, близкое к нулю, т.е. на 0.01. Это удерживает спортсмена на месте, однако, смотреть он будет на шайбу.
Подготовка к матчу
Это состояние ответственно за то, чтобы игроки возвращались на свои позиции и останавливались там. Обновим наш класс Athlete
:
Ниже вы сможете увидеть результат добавления ИИ в игру. Нажмите клавишу G и игроки переместятся в случайные позиции. Затем они встанут на нужные места:
Вывод
Этот урок дает вам основу для реализации хоккея, используя рулевое поведение и конечный автомат. Комбинируя эти концепции, игроки могут двигаться как самостоятельно, под управлением ИИ, так и следуя за курсором вашей мыши. Также хоккеист может ударить по шайбе.
Используя конечный автомат с двумя состояниями мы научили игроков готовиться к матчу и занимать положенные места. В следующем уроке вы узнаете, как организовать нападение и научить игроков забивать голы!
Перевод статьи “Create a Hockey Game AI Using Steering Behaviors: Foundation”
21К открытий21К показов