Создание платформеных игр
Игры Платформы - очень распространены, в особенности на устройствах типа Game Boy. В платформенной игре ты смотришь на сцену со стороны. Игрок как правило управляет персонажем, который путешествует по миру, где это только можно. Этот мир состоит из платформ. Игрок может ходить по этим платформам, прыгать или перепрыгивать c одной платформы на другую, использовать лестницы или веревки, чтобы забираться на всевозможные возвышенности и т.д. На платформах находятся объекты, которые необходимо собираться, враги которых следует избегать или уничтожать (в основном или стреляя в них, или прыгая на них сверху), выключатели - которые требуется нажимать, чтобы открывать проходы и т.д. Также игроку обычно требуется определенный навык чтобы перепрыгивать через опасные области. В некоторых платформенных играх ты видишь сразу весь уровень, но в большенстве из них видима всего часть уровня вокруг персонажа. В такой ситуации, поиск пути становится дополнительным испытанием.
Создание хорошей платформенной игры задача не простая, но только не с Game Maker. Самыми сложными являются три следующих момента:
* Создание естественного движения для персонажа.
* Создание достаточного разнообразия монстров, фонов и т.д.
* Тщательное проектирование уровней, так чтобы они были забавными для игры и становились все более и более трудными.
В этой обучающей программе я расскажу и подскажу, дам некоторые намеки относительно того, как создать платформенные игры, используя Game Maker. Обучающая программа требует, чтобы ты имел Game Maker версии 4 или более поздний. Обучающая программа сопровождается множеством демонстрационных игр. Это - не полные игры. Каждая состоит только из одного уровня, демонстрирующего лишь некоторые определенные аспекты. Ты можешь использовать их как основу для своих будущих платформенных игр.
Основа
Мы начнем с наиболее простой игры платформы. Ты можешь найти ее в файле platform_basic.gmd. В каждой платформенной игре существует два основных объекта: персонаж, управляемый игроком и блочный объект - который используется для пола (платформ) по которым игрок может ходить и стен, являющихся для игрока естественным ограничетелем движений. Нам понадобится два спрайта: один для персонажа и один для блока. Для персонажа мы используем простой мяч. Для блока возбмем (не-прозрачный) черный квадрат. Создаем два объекта: твердый блочный объект со спрайтом блока и объект персонажа.
Горизонтальное движение
Теперь мы должны определить движение персонажа. Проблема состоит в том, что наш герой должен идти по полу, верхней его части. При этом он не должен пересекать пол (не должен проваливаться). Если персонаж прыгает или падает с платформы, он должен правильно приземлиться на следующую платформу. Существует множество различных способов, посредством которых персонаж может ходить, прыгать и падать. Разные игры используют различные модели. Обычно для управления движением мы используем только три клавиши. Клавиша со стрелкой "влево" перемещает наш персонаж налево, клавиша со стрелкой "вправо" должна перемещать его направо и клавиша "вверх" или клавиша "пробел" заставляет его подпрыгивать.
Для начала давай рассмотрим движение влево и вправо. Первый способ, сделать его независимым от игрока, чтобы играющий мог только изменять направление движения героя, когда тот находится на платформе или в воздухе, когда он прыгает или падает. Даже при том, что второй вариант не совсем естественен (ведь в природе довольно трудно начать перемещаться влево, в то время как падаешь вниз), тем не менее он как правило позволяет добиться хорошего результа - (получаются более играбельные игрушки) и также они оказываются фактически проще для осуществления. Второй способ - когда ты нажимаешь и удерживаешь нажатой клавишу, герой начинает движение и перемещается он либо с постоянной скоростью, либо с ускорением. Остановимся на первом варианте. К сожелению мы не можем использовать действия для установки направления движений. Причина в том, что это создало бы помехи вертикальному движению, используемому для прыжков и падения (и позже и восхождения). Вместо этого мы просто изменим позицию. Ты также можешь использовать для этого действие или код. Использование действий мы применим в следующем. В событии для клавиши "влево" (на keypad) нам нужно одно действие, чтобы проверить, является ли позиция пустой. Указываем, относительное значение -4 и 0. (Так мы проверим, является ли позиция, слева от текущей пустой). Следующее действие, которое выполняется только если позиция действительно истинна, позволяет персонажу переместится относительно позиции -4, 0. Сделай тоже самое для события правой клавиши, но теперь используй 4 а не -4. В коде мы печатаем следующее:
{
if place_free(x-4,y) x -= 4;
}
Цифра 4 указывает скорость, которую ты можешь изменить, если хочешь.
Прыжки
Далее мы нуждаемся в вертикальном движении. Его добиться более сложно. Чтобы позволить персонажу падать, мы можем использовать гравитацию (силу тяжести). Но необходимо также добится чтобы движение прекратилось, когда герой коснется пола. Помимо этого, нужно указать максимальную скорость падения, иначе персонаж будет двигаться слишком быстро. (Это будет выглядеть не очень красиво, а еще может вызывать и некотрые проблемы в выполнении). В результате мы помещаем следующую часть кода в шаговом событии (step event) персонажа. Он устанавливает силу тяжести, основанную на том, находится ли что-то под персонажем (проверяем, является ли позиция 1 пикселя ниже персонажа свободной). Также он ограничивает вертикальную скорость.
{
// устанавливаем силу тяжести (гравитация)
gravity_direction = 270;
if place_free(x, y+1)
gravity = 0.5
else
gravity = 0;
// ограничиваем скорость
if (vspeed > 12) vspeed = 12;
}
Далее мы должны приземлиться. Что еще труднее чем может показаться. Это происходит, когда персонаж сталкивается с блочным объектом. В этом событии столкновения (collision event) мы должны установить вертикальное движение на 0. Но оно может оставить персонаж, зависшим немного в воздухе над землей. (Причина в том, что персонаж перед столкновением помещается назад в его предыдущую позицию). Чтобы избежать этого - нужно переместить персонажа вниз, до тех пор - пока он не коснется блока. Делаем, но процесс должен быть выполнен только тогда, когда соблюдаются два условия: персонаж падает вниз (так vspeed > 0) и непосредственно ниже персонажа имеется блок так not place_free(x,y+vspeed)). Иначе может произойти (редкий) случай, когда персонаж неожиданно подпрыгивает вверх или вниз. Все вышеперечисленное достигается следующей частью кода, который должен быть помещен в событие столкновения с блоком:
{
if (vspeed > 0 && not place_free(x,y+vspeed)) move_contact(270);
vspeed = 0;
}
Наконец мы должны позволить персонажу подпрыгнуть, когда нижимается клавиша со стрелкой "вверх". Но это должно произойти только, когда персонаж находится непосредственно на полу. Сее может быть достигнуто посредством следующего кода.
{
if (not place_free(x,y+1)) vspeed = -10;
}
Возможно тебе придется немного изменить значением 10 для вертикальной скорости и значение 0.5 для сопротивления, чтобы получить движение, которое необходимо.
Что-ж, основа для нашей платформенной игры готова. Создай уровень с несколькими полами и стенами, создав их из блоков и чтобы персонаж, находясь внутри уровня мог перемещаться по всему уровню. Обрати внимание, что все, что выполняет наш вышеуказанный код, может быть достигнуто и при использовании действий. В виде действия не доступна только функция move_contact().
Улучшение графики
Базовая платформенная игра, которую мы создали в предыдущем разделе работала, но выглядела она не очень привлекательно.
Имеются две вещи, которые мы хотим изменить: это внешний вид главного героя и внешний вид фоновых изображений. Рассматриваемый вариант можно найти в файле platform_graphics.gmd.
Изображение для персонажа
Давай начнем с графики отображающей нашего главного героя. Мы будем использовать два разных (не-анимированных) спрайта: один для персонажа, смотрящего налево и один для смотрящего направо. И теперь нужно просто поместить в событие для клавиши (Left) действие (Change the sprite) и выбрать соответствующий спрайт (где персонаж смотрит влево). Аналогичное действие мы выбираем и для клавиши (Right), только здесь выбираем спрайт смотрящий уже направо. Не рекомендую тебе включать проверку точного столкновения (precise collision checking) для этих двух спрайтов. Иначе тебе не избежать ситуации, когда персонаж твоей игры в момент прыжка будет зацепляться за края платформ. И наконец обязательно проверь, чтобы ограничивающие поля каждого из этих двух спрайтов были одинаковыми. Иначе, при повороте слева на право и наоборот - в некоторых игровых ситуациях могут возникнуть проблемы. (Для этого ты всегда можешь воспользоваться полями в (Bounding Box) включив опцию (manual)).
В более сложных играх ты скорее всего захочешь использовать анимированные спрайты. В этом случае тебе также понадобится статичный спрайт для твоего персонажа, отображающий его в момент, когда он неподвижно стоит на месте. Возможно ты также захочешь добавить спрайты для персонажа прыгающего, падающего, стреляющего и т.д. В этом случае придется использовать действие (Change the sprite) в различных в событиях. В частности, в событии ты скорее всего используешь статичный спрайт на котором персонаж просто стоит на месте. Кроме того, ты можешь используя действия рисования (draw) - нарисовать нужный спрайт в событии рисунка (drawing event) в зависимости от ситуации. Например, ты можешь использовать проверку xprevious
Платформы и стены
Вторая наша задача - улучшить фон и платформы. Здесь мы используем стандартную методику. Мы будем рисовать все наши замечательные платформы и стены прямо на фоновом изображении. Для этого мы используем опцию для создания плиточного фона (смотри главу 15 документации). Ты можешь использовать второй фон, чтобы придать платформам хороший фон. В этом случае не забудь сделать фон с платформами прозрачным.
Мы помещаем объекты блока в соответствующие места поверх стен и платформ, нарисованных тобою на фоновом изображении. Далее, сделав блочный объект невидимым ты добьешся того, что на экране будут отображаться не черные блоки, а красивый фон. Но блочные объекты при этом - реально остаются там, куда ты их помещал - следовательно персонаж не сможет проходить сквозь стены и будет приземляться именно на платформах. И все бы хорошо, если бы не одна проблемка. Блочные объекты размером 16x16 могут оказаться слишком большими, чтобы качественно перекрыть фон. В связи с этим мы создаем несколько других блочных объектов размером 16x8 и 8x16. Опять делаем их твердыми. Чтобы избежать необходимости, определять события столкновения также и для них, в окне свойств объетка, во вложении (Advanced) включи для опцию (parent) для блочного объекта. Таким образом они будут обработаны точно также, как и большой блок.
Угрозы и преодоления
Просто прыгать с одной платформы на другую занятие довольно скучное. Ты определенно нуждаешся в каком-то вызове, в какой-нибудь задаче, которую следует решить. В этом разделе мы обсудим именно это. Загрузи файл platform_monsters.gmd чтобы понять о чем идет речь.
Монстры
Давай для начала добавим в нашу игру несколько монстров. Мы создадим двух монстров, первый из которых марширует на платформе слева направо, а второй, летает в небе справа налево. Первого можно будет уничтожить, прыгнув ему сверху на макушку, второй же будет бессмертным и его нужно будет держаться стороной.
Начнем с монстров гуляющих по платформам. Для них нужно два спрайта. Один с монстром, смотрящим влево и другой с монстром, развернутым вправо. После чего создаем объект монстра. В событии создания (creation event) мы позволяем ему двигаться вправо с определенной скоростью. Всякий раз, когда он достигает стены, монстр изменяет свою горизонтальную скорость на обратную. Чтобы нарисовать нужный спрайт, мы помещаем следующий код в событие рисования:
{
if (hspeed > 0)
draw_sprite(sprite_monsterr,-1,x,y)
else
draw_sprite(sprite_monsterl,-1,x,y);
}
Основываясь на значении переменной hspeed (которая определяет горизонтальную скорость) мы рисуем нужный спрайт.
Чтобы избегать падения монстров с платформы, мы вводим другой объект, который назовем маркером (marker). Этим маркером будет невидимый синий блок. Всякий раз, когда монстр касается его, он изменяет направление своего движения на обратное.
Когда персонаж касается монстра, монстр или персонаж должен погибнуть. Чтобы выяснить, что должно произойти, в событии столкновения (collision) персонажа с монстром, мы выполяем следующую проверку:
vspeed > 0 && y < other.y+8
Если результат истинен (true), персонаж движется вниз и падает на голову монстру. Это означает, что монстр должен быть умерщвлен. (В примере мы заменяем спрайт монстра на спрайт мертвого монстра, который уничтожает себя через некоторое время. Это создает очень хороший графический эффект). В этой простой игре, гибель персонажа соответствует перезапуску уровня, который может быть достигнут несколькими простыми действиями.
Летящий монстр делается проще. Мы поторяем для него все те же действия. Только в событии столкновения персонажа с летящим монстром, нет никакой проверки.
Ты можешь добавить более разнообразных монстров, например с различной скоростью движения, что сделает их более жетскими противниками. Ты можешь также сделать монстра или камень, который падает или перемещается вверх и вниз. Одним словом включи свое воображение.
Ямы
Большинство платформенных игр требуют тщательно выверенных прыжком, чтобы избежать падения в ямы. Падение в яму обычно грозит персонажу гибелью. Чтобы претворит задуманное, мы добавляемся новый объект, названный смертью (death). Этим объектом является красный блок, который мы делаем невидимым. Ты можешь поместить его на дно ямы. (На фоновом изображении ты можешь разместить в яме несколько ьаких объектов). В событии столкновения персонажа с объектом (death) проигрывается звук, затем небольшая пауза и в заключении происходит перезапуск комнаты. Ты можешь также сделать ямы, которые не имеют дна (этакий провал). В этом случае ты добавляешь аналогичное действие в событии (outside) (в других событиях) персонажа, можно вставить проверку y > room_height чтобы удостовериться, что персонаж упал, когда он выпрыгивает за пределы игрового поля.
Собирание предметов
В большинстве игр платформ играющему приходится помимо всего, собирать всякие предметы. Как правило тебе приходится или собирать некоторые объекты или ловить какие-то предметы. В нашем примере игрок может собирать грибы. Поэтому, нужно создать объект гриба. Для разнообразия, спрайт гриба содержит 10 различных изображений грибов. Объект гриба выбирается наугад во время выполнения события создания. Чтобы добиться этого мы в событии (Create) помещаем действие (X=2) и устанавливаем в нем переменную (variable) image_single и новое значение для данной переменной random(10). В событии столкновения (collision) персонажа с грибом мы проигрывем звук, уничтожаем (destroy) объект (other) и добавляем 10 очков к текущему счету.
В некоторых платформенных играх, собирание вещей имеет помимо увеличения игрового счета и более функциональный момент. Например, ты можешь получить дополнительную жизнь, когда собрано определенное количество объектов. Также может имется предмет, который восстанавливает твое здоровье (делает так, что монстры не убивают тебя, а лишь ослабляют твое здоровье), заставляет тебя двигаться быстрее, прыгать выше и т.д.
Следующий уровень
Конечно же должен существовать способ окончания уровеня, такой, чтобы игрок мог перейти на следующий уровень. Для этого, мы создаем объект (levelexit). Когда персонаж добирается до него, он перемещается в следующий уровень. В примере это сделано довольно просто. Мы всего лишь добавляем тест room==room_last. Если результат теста истинен (true), то мы перемещаемся на следующий уровнень. но так как пример содержит лишь один уровень, а значит мы находимся на последнем и не имеем возможности продолжить игру - вместо этого появляется список лучших игровых результатов и игра будет запущена снова.
Ты можешь сделать так, чтобы объект (levelexit) появлялся только тогда, когда например собраны все грибы. Для этого, в событии создания (levelexit) объекта, помещаем действие (Jump to position) и указываем значение для координат -100, -100 (убираем его с экрана). Теперь в событии шага подставляем действие проверки (If number instances) - выбираем объект гриба равный (equal) значению 0. И если это так, перемещаем объект (levelexit назад) в его исходную позицию - это можно сделать поставив после проверки дейстиве (Jump to start position).
Дополнительные перемещения
Наша текущая игра сожержит лишь некоторые элементарные перемещения. Главный персонаж может двигаться влево и право, и еще может прыгать. Чтобы сделать игру более интересной и более активной, давай добавим в нее еще несколько интересных перемещений. Готовый пример можно найти в файле platform_motions.gmd.
Наклонные ступеньки
Прикольно если бы игрок имел возможность подниматься на наклонным ступенькам (вниз, он будет спускаться автоматически в результате падения). Чтобы сделать это, мы должны изменить код в событии клавиши (left). Печатаем там следующее:
{
for (i=0; i<= 8; i +=1)
{
if place_free(x-4,y-i) { x -= 4; y -= i; exit; }
}
}
Это должно быть немного сложно для понимания. Данный код пробует все варианты для i от 0 до 8. Для каждого из них он проверяет, является ли позиция x-4, y-i пустой. Если это так, код перемещает персонаж куда следует и отключается. Таким образом программа сначала проверяет, можем ли мы двигаться налево. Если нет, он пробует переместить один пиксел. Если не работает, он пробует два пиксела и т.д. (Мы продолжаем до 8 - позволяя тем самым идти по лестнице). Подобный код должен быть помещен также в событие для клавиши (Right). Это пожалуй и все.
Лестницы
Народ в платформенных играх просто нуждается в различных лестницах, по которым он сможет перемещаться с одной платформы на другую. Это перемещение потребует от нас небольшой работы. Лестница будет представлена узким вертикальным блоком, который является невидимым (настоящая лесенка или виноградная лоза, используемая для восхождения, нарисована на фоне и не является твердым телом. Когда персонаж не контактирует с лесенкой, его движение должно оставаться преждним. Но когда он начинает контактировать с элементами лесенки - его движения изменяются. Во первых, наш персонаж не должен падать. Для этого в событии шага (step), в выполняемый код, мы должны внести изменения и добавить следующий кусок в конце имеющегося кода:
// проверка для лестницы
if place_meeting(x,y,ladder)
{ gravity = 0; vspeed = 0; }
Во вторых, должны измениться действия для клавиш. Когда персонаж оказывается на лестнице, клавиша со стрелкой "вверх" должна вместо прыжка просто переместить его вверх. В связи с этим обнавляем код:
{
if place_meeting(x,y,ladder)
{
if place_free(x,y-3) y -= 3;
}
else if (not place_free(x,y+1)) vspeed = -10;
}
Также, клавиша (Down) должна медленно перемещать персонажа вниз по лесенке, используя подобную часть кода. И конечно же, ты захочешь создать отдельный спрайт для поднимающегося персонажа - в событии шага (step), следует изменить спрайт для отображения объекта при контакте с лесенкой.
Что дальше?
Вся вышеизложенная информация, как мы надеемся, дала тебе общие понятия и описала способ создания платформенных игр. Теперь твоя очередь. Ты можешь вооружившись полученными знаниями, и используя эти методы плюс свое воображение, чтобы создать действительно хорошую латформенную игру. Запомни, что наиболее важная часть платформенных игр - уровни. Начни создание уровней один за другим. Поиграй с ними, пока не поймешь, что создал что-то действительно интересное. Старайся как можно больше вводить в игру какие-то необычные моменты. На этот счет имеется несколько идей, которые ты сможешь использовать:
разнообразные монстры, например прыгающие шарики и стреляющием монстры, в которых и сам игрок может стелять (возможно только после нахождения стрелкового оружия);
ключи, которые ты должен найти, чтобы открыть двери;
мины, помещеные куда-нибудь и уничтожающие, монстр (или самого персонажа) когда те встают на них;
вода, чтобы плавать в ней (полностью изменяются движения; отсутствует сила тяжести или незначительная сила тяжести, пока ты не достигаешь поверхности, ограничение времени - прежде чем у тебя закончится запас кислорода, воздушные пузырьки, которые можно захватывать и т.д.); стены и пол котрые ты можешь уничтожить, например стреляя в них или прыгая на них с силой;
трамплины, которые позволят тебе прыгать выше обычного;
платформы, которые появляются и исчезают;
односторонние улицы;
перемещающие платформы (это не просто)!