Создание игр для мобильных телефонов - Майкл Моррисон
Шрифт:
Интервал:
Закладка:
Если ваша главная цель – это разработка игры, которая развлекает и захватывает действием, выбирайте самый простой ИИ. Попробуйте сначала использовать самый простейший ИИ вне зависимости от ваших целей, вы в любой момент сможете усложнить его. Если вам кажется, что в вашей игре не подойдет ни один из описанных мною типов ИИ, вы можете поискать другие варианты, подобрать что-то более подходящее для решения задачи. Важно отметить, что на разработку ИИ должно быть отведено много времени, поскольку 90 % уйдет на то, чтобы заставить работать алгоритм так, как это требуется.
С чего начинать работу? Многие программисты любят писать код непосредственно при разработке алгоритма. Хотя такой подход может давать хорошие результаты в некоторых случаях, все же лучше предварительно провести разработку на листе бумаги. Кроме того, постарайтесь ограничить разработку областью игрового ИИ. Начните с небольшой карты или сетки с простыми правилами совершения ходов. Напишите код, проводящий одного оппонента из точки А в точку Б.
Затем постепенно усложняйте код, создавая алгоритм шаг за шагом. Если вы усвоили основы создания ИИ и достаточно сообразительны, чтобы построить дополнительные фрагменты алгоритма, в результате вы получите общий алгоритм, который можно применять в различных играх.
Хороший способ попрактиковаться с созданием ИИ – это написать алгоритм игры компьютерного противника в настольной игре, например, шашки. Для большинства популярных игр есть подробные описания ИИ, которые вы можете найти в сети. Другой хороший способ потренироваться – это модифицировать уже существующую игру, попробовать сделать управляемых компьютером персонажей немного умнее. Например, вы могли бы изменить игру Henway так, чтобы спрайты ускорялись или замедлялись, тем самым, усложняя задачу цыпленку. Или вы можете создать собственный спрайт, который знает, как преследовать другие спрайты на различных уровнях агрессии… экспериментируйте!
Учим спрайты думать…
Ранее в этой главе речь шла о преследующем блуждающем искусственном интеллекте. Объект достаточно умен, чтобы преследовать другие объекты, обычно управляемые игроком. Теперь вы готовы создать и реализовать спрайт, который будет преследовать другие объекты. Вы сможете улучшить игру High Seas, разработанную в предыдущей главе, сделать ее интереснее.
Разработка преследующего спрайта
Условия для разработки преследующего спрайта таковы: есть целевой спрайт, преследователь, преследователь постоянно движется в направлении цели. Представьте игру в салки, в которой вы – догоняющий, точно так же себя ведет и преследующий спрайт. Чтобы понять, как может работать такой спрайт, вы должны представить себе игру в салки в заторможенном состоянии. Например, предположим, что вы расположены в точке с координатами XY, например, недалеко от крыльца дома. Вы можете использовать любую единицу измерения, которую пожелаете, – метры, аршины, попугаи. все что угодно! Пусть тот, кого вы будете догонять, будет расположен в другой точке с координатами XY относительно крыльца дома.
Зная координаты преследователя и преследуемого, вы обладаете всем необходимым для планирования дальнейших действий. Чтобы определить в каком направлении следует двигаться относительно оси X, из координаты X преследуемого вычтите координату X вашего положения. Отрицательное значение говорит о том, что вы должны двигаться на запад, а положительное – на восток. Аналогичные вычисления следует сделать с координатами Y. Отрицательный результат говорит о том, что вы должны двигаться на север, а положительный – на восток.
На рис. 13.3 показано, как в рассмотренном примере принимается решение двигаться в определенном направлении.
Рис. 13.3. Направление, в котором должен двигаться преследователь, легко определить простым вычитанием координат XY преследователя и преследуемого
Рисунок 13.3 иллюстрирует, как, зная координаты преследующего и преследуемого, вы, используя простые вычисления, можете определить направление движения преследующего. Стоит отметить, что показанный на рисунке подход к преследованию имеет одну существенную проблему, с которой вы сталкиваетесь при попытке написания кода. Она заключается в том, что преследователь не идеален. Иначе говоря, преследующий постоянно подстраивает направление своего движения даже в том случае, если он бежит прямиком к цели. Это происходит потому, что преследователь старается предугадать поведение преследуемого. Решение этой проблемы заключается в том, чтобы задать область значений разницы координат, в которой преследователь не будет ничего предпринимать, чтобы догнать преследуемого. Чтобы понять, о чем я говорю, посмотрите на рис. 13.4.
Рис. 13.4. Установив границу, вы решите проблему постоянного изменения направления в том случае, когда преследователь уже находится на одной линии с преследуемымИдея определения границы для преследователя – это ограничить движение преследующего, когда он находится достаточно близко к преследуемому. Помните, что вы работаете в координатах XY, поэтому даже если по одной из координат преследователь близок к своей цели, по другой он может находиться очень далеко. Однако граница должна исключить движение преследователя по зигзагу, поскольку он уже находится на одной линии с преследуемым, поэтому нет необходимости изменять направление. Если эти рассуждения показались вам не более чем теорией, то, вероятно, реальный код поможет все расставить на свои места. Вы, несомненно, оцените пользу преследующего спрайта, когда чуть позже будете работать над совершенствованием игры High Seas 2.
Программирование спрайта преследователя
Класс ChaseSprite – производный класс от стандартного Sprite, и это неудивительно. Переменные класса ChaseSprite могут дать представление о внутреннем устройстве класса. Ниже приведены наиболее важные переменные, объявленные в классе ChaseSprite:
private int speed;
private TiledLayer barrier;
private boolean directional;
private Sprite chasee; //Спрайт преследуемого
private int aggression; // 0 – 10Переменная speed хранит значение скорости преследующего спрайта, скорость задается в пикселях за игровой цикл. Каждый раз, когда спрайт преследователя совершает движение в направлении преследуемого спрайта, он перемещается на число пикселей, задаваемое этой переменной. Переменная barrier указывает на слой, ограничивающий перемещение спрайта преследователя. Важно отметить, что этой переменной вы можете присвоить значение null, если не хотите, чтобы перемещения этого спрайта были чем-то ограничены. Например, если вы создали лабиринт в замке и населили его всевозможными существами, то, вероятно, для привидений не имеет смысла создавать преграды, поскольку они могут свободно проходить сквозь стены. Или, например, в игру High Seas вы можете добавить дракона, которому земля – не помеха.
Но вернемся к классу ChaseSprite. Переменная directional определяет, есть ли у спрайта направление или нет. Направленный спрайт, очевидно, имеет различимые стороны, это означает, что его фреймы должны содержать изображения, соответствующие перемещению спрайта в определенном направлении, а не только анимацию движений. Хотя это вовсе не спрайт преследователя, корабль из игры High Seas – это хороший пример направленного спрайта, а спрайт осьминога – это пример спрайта, который не имеет направленности, он перемещается, не разделяя направления.
Переменная chasee – это преследуемый спрайт, он очень важен для корректной работы спрайта преследователя. Наконец, переменная aggression хранит целое число от 0 до 10, которое определяет, насколько агрессивно себя ведет спрайт. Значение 0 соответствует наименее агрессивному спрайту, который не старается преследовать вовсе, а значение 10 соответствует спрайту, который беспрестанно преследует свою жертву. При разработке игр с преследующими спрайтами поэкспериментируйте с этой переменной, чтобы добиться желаемого результата....Совет Разработчику
По мере развития игровых действий целесообразно увеличивать значение переменной, определяющей агрессию спрайта преследователя, – это сделает игру интереснее. Вы можете связать агрессию спрайтов с уровнем игры (количеством набранных игроком очков) или просто с прошедшим от начала игры временем.
Переменные класса ChaseSprite инициализируются конструктором ChaseSprite() (листинг 13.1).
Листинг 13.1. Конструктор ChaseSprite() вызывает родительский конструктор и инициализирует переменные класса
public ChaseSprite(Image image, int frameWidth, int frameHeight, int chaseSpeed,
TiledLayer barrierLayer, boolean hasDirection, Sprite chaseeSprite,
int aggressionLevel) {
super(image, frameWidth, frameHeight);
// инициализация генератора случайных чисел
rand = new Random();
// установить скорость
speed = chaseSpeed;
// установить слой-барьер
barrier = barrierLayer;
// установить, направленный ли спрайт
directional = hasDirection;
// установить преследуемый спрайт