Как написать простейший платформер в Game Maker Studio

Результат

Я покажу, как реализовать передвижение, коллизию, прыжки, гравитацию, ускоряющие платформы, платформы для прыжков, смерть от шипов и падения за карту, переход на следующий уровень и порталы.

Перед началом желательно иметь хоть какие-нибудь навыки работы с Game Maker Studio. Рекомендую ознакомиться с интерфейсом программы.

Передвижение игрока

Создадим объект oPlayer (в дальнейшем все названия ресурсов будут начинаться с соответствующей приставки, чтобы понимать, что это за ресурсы. Для объекта (object) — «o», для комнаты (room) — «r» и т. д.). Также понадобится нарисовать спрайт или загрузить уже готовый, и привязать его к объекту. В моем случае это простой белый квадрат 48x48.

Как написать простейший платформер в Game Maker Studio

В событии Create объявим следующие переменные:

xDir - направление движения игрока по горизонтали. Переменная будет равна:
-1 — если игрок идет налево;
1 — если игрок идет направо;
0 — если игрок стоит на месте.

stepLength - длина шага игрока в пикселях. Пускай переменная будет равна 10.

dx - сдвиг по горизонтали. Каждое обновление комнаты (по умолчанию — 60 обновлений в секунду) игрок будет сдвигаться на dx пикселей. dx будет вычисляться перемножением xDir и stepLength.

Как написать простейший платформер в Game Maker Studio

Переменные можно объявить другим способом: в специальном разделе Variable Definitions.

Как написать простейший платформер в Game Maker Studio

В событии Step напишем следующее:

xDir = -keyboard_check(ord("A")) + keyboard_check(ord("D")); dx = xDir * stepLength; x += dx;
Как написать простейший платформер в Game Maker Studio

Переменная x относится к тем переменным, которые есть в каждом созданном вами объекте. Они определяются автоматически, без вашего участия, и выделяются зеленым цветом в коде. Список всех таких переменных.

Первая строка вычисляет направление движения. Функция keyboard_check(key) принимает в качестве аргумента клавишу и возвращает true, если она нажата. Функция ord(string) принимает в качестве аргумента строку и преобразует ее в необходимый тип данных для аргумента функции keyboard_check(key). Таким образом, при удержании клавиши "A" переменная xDir становится равной -1, а при удержании клавиши "D" - 1.

Вторая строка вычисляет dx.

Третья строка увеличивает x на dx пикселей, то есть двигает игрока.

Создаем комнату и добавляем на слой Instances экземпляр объекта игрока.

Как написать простейший платформер в Game Maker Studio

Запускаем и убеждаемся, что все работает как надо.

Коллизия

Вместо того, чтобы обрабатывать каждый объект, в который можно врезаться и на котором можно стоять, создадим абстрактный объект oSolid («твердый» объект), от которого будем наследовать другие объекты, которые мы хотим наделить коллизией.

Как написать простейший платформер в Game Maker Studio

Здесь никаких переменных и событий создавать не надо: код для взаимодействия с объектом напишем внутри oPlayer в событии Step. Перепишем его так, чтобы событие выглядело следующим образом:

xDir = -keyboard_check(ord("A")) + keyboard_check(ord("D")); dx = xDir * stepLength; if (!place_meeting(x + dx, y, oSolid)) //эта строчка новая x += dx;
Как написать простейший платформер в Game Maker Studio

place_meeting(x, y, obj) нужна для проверки пересечения прямоугольников коллизий двух объектов. Она принимает три аргумента:
x - позиция первого объекта по оси x;
y - позиция первого объекта по оси y;
obj - имя второго объекта или id его экземпляра.
Функция возвращает true, если объекты пересекаются и false - если нет. Важно то, что проверка осуществляется не в одной лишь точке (x; y), а сразу во всех точках прямоугольника вызывающего объекта. Для проверки коллизии в одной точке имеется функция position_meeting(x, y, obj), но она нам не понадобится. Используя place_meeting(x + dx, y, oSolid), мы проверяем пересечение игрока с твердым объектом, как если бы игрок был сдвинут на dx пикселей. И только убедившись, что пересечения нет, меняем координату игрока.

Теперь нужно создать объект oWall, установить ему родителя oSolid и привязать к нему какой-нибудь спрайт. В моем случае это черный квадрат 64x64. Позже в редакторе комнаты экземпляры этого объекта можно будет растянуть.

Как написать простейший платформер в Game Maker Studio

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

Есть одна проблема: между игроком и стеной иногда появляется небольшой зазор, ведь объект либо двигается на stepLength пикселей, если нет столкновения, либо вообще не двигается, если оно обнаружено. Таким образом, если переменная stepLength, например, равна 10, а зазор между игроком и стеной — 5 пикселей, экземпляр объекта игрока так и не встанет вплотную к стене. Решается это тем, что мы попиксельно будем двигать игрока в сторону его движения, пока зазор не исчезнет. В этом поможет функция sign(n), которая возвращает:
-1 — если аргумент n отрицательный;
1 — если аргумент n положительный;
0 — если аргумент n равен нулю.

xDir = -keyboard_check(ord("A")) + keyboard_check(ord("D")); dx = xDir * stepLength; if (!place_meeting(x + dx, y, oSolid)) x += dx; else while (!place_meeting(x + sign(dx), y, oSolid)) x += sign(dx);
Как написать простейший платформер в Game Maker Studio

Проверяем.

Теперь все работает.

Гравитация и прыжки

В событии Create объекта oPlayer объявим переменную onGround, она нужна для того, чтобы проверять, стоит ли игрок на поверхности или же находится в воздухе.

Помимо нее нам понадобится переменная dy, которая будет работать по тому же принципу, что и dx: y будет сдвигаться на dy пикселей каждое обновление комнаты при отсутствии препятствий.

Для гравитации понадобится переменная gravitation. dy будет постепенно складывать это значение, когда игрок находится в воздухе, тем самым увеличивая скорость падения. Пусть это значение будет равно 1.75.

Для реализации прыжка нужна переменная jumpImpulse, которая будет описывать силу, с которой объект игрока будет прыгать. Значение переменной должно быть меньше нуля, пусть оно будет равно -21.

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

Как написать простейший платформер в Game Maker Studio

Вообще, jumpImpulse и gravitation могут иметь совершенно другие значения. По желанию можно сделать так, чтобы они менялись в зависимости от комнаты, в которой вы находитесь, но пока что обойдемся без этого.

В событии Step добавим следующий код:

if (onGround) if (keyboard_check_pressed(ord(" "))) dy = jumpImpulse; if (!place_meeting(x, y + dy, oSolid)) y += dy; else { while (!place_meeting(x, y + sign(dy), oSolid)) y += sign(dy); dy = 0; } dy += gravitation; onGround = place_meeting(x, y + 1, oSolid);
Как написать простейший платформер в Game Maker Studio

Разберем его по порядку:

if (onGround) if (keyboard_check_pressed(ord(" "))) dy = jumpImpulse;

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

Разница между функциями keyboard_check_pressed(key) и keyboard_check(key) в том, что при вызове первой она возвращает true только в момент нажатия клавиши (один раз), а при вызове второй — в любой момент, когда клавиша удерживается.

if (!place_meeting(x, y + dy, oSolid)) y += dy; else { while (!place_meeting(x, y + sign(dy), oSolid)) y += sign(dy); dy = 0; }

Здесь все то же самое, что и в случае с проверкой коллизии по горизонтали, только при обнаружении препятствия нужно обнулить dy, иначе к ней так и будет прибавляться gravitation, пока dy не станет настолько большой, что игрок начнет проваливаться под "твердые" объекты.

dy += gravitation;

Здесь просто увеличиваем скорость падения объекта игрока за счет гравитации.

onGround = place_meeting(x, y + 1, oSolid);

Эта строчка проверяет, стоит ли на земле игрок.

Переход на следующий уровень

Создадим объект oDoor и привяжем к нему спрайт.

Как написать простейший платформер в Game Maker Studio

Создаем в oPlayer событие столкновения с oDoor.

Как написать простейший платформер в Game Maker Studio

Пишем в нем room_goto_next();.

Как написать простейший платформер в Game Maker Studio

Это все. Осталось лишь добавить еще одну комнату и поставить дверь.

Смерть от шипов и падения за карту

Создадим пустой абстрактный объект oKilling («убивающий» объект), от него унаследуем oTriangle (треугольник) и для разнообразия oTriangleSmall (маленький треугольник).

Как написать простейший платформер в Game Maker Studio

Объявим в событии Create объекта oPlayer переменную isDead. В том же oPlayer добавляем событие пересечения с oKilling и событие выхода за пределы комнаты (Outside Room). И там, и там пишем isDead = true;.

Как написать простейший платформер в Game Maker Studio

В событии Step добавляем две строчки:

if (isDead) room_restart();

room_restart() перезагружает комнату. Каждый раз, когда игрок будет натыкаться на шип или падать в пропасть, комната будет перезапускаться, как если бы вы вошли в нее в первый раз: все экземпляры объектов пересоздадутся и появятся на начальной позиции, если до этого были подвинуты.

Порталы

Создадим объект oPortal и в событии Create объявим переменную pair (пара). Эта переменная будет хранить id другого портала, к которому игрок будет телепортироваться. Таким образом вы сможете получить доступ ко второму порталу через первый.

Как написать простейший платформер в Game Maker Studio

От oPortal я унаследовал два объекта: oPortalBlue и oPortalPink, у каждого свой соответствующий названию спрайт.

Как написать простейший платформер в Game Maker Studio

Создадим новую комнату и добавим туда несколько порталов.

В редакторе комнаты если нажать на какой-нибудь слой, слева высветится меню свойств этого слоя. Если выделить слой Instances, в этом меню будут перечислены все экземпляры объектов, находящиеся на этом слою, там же будут написаны их идентификаторы.

Как написать простейший платформер в Game Maker Studio

При двойном нажатии на один из экземпляров высветится меню, где можно настроить этот конкретный экземпляр: изменить значения переменных, идентификатор или код создания. Изменение параметров выделенного экземпляра не затронет остальные экземпляры этого же объекта в комнате. В разделе Creation Code можно указать, какой портал будет являться парой для выделенного. Для этого пишем pair = *идентификатор другого экземпляра портала*;.

Как написать простейший платформер в Game Maker Studio

В моем случае id другого портала — inst_6CB6ED9F, у вас это название будет другим. По желанию это наименование можно изменить на более понятное, например, instPortalBlue1.

То же самое следует проделать с остальными тремя порталами.

Теперь в объекте oPlayer добавим событие пересечения с oPortal и добавим этот код:

if (keyboard_check_pressed(ord("E"))) { x = other.pair.x; y = other.pair.y; }
Как написать простейший платформер в Game Maker Studio

other в любом событии пересечения двух объектов — это ссылка на экземпляр объекта, с которым пересекся экземпляр, вызвавший это событие.

В данном случае other - портал, с которым пересекается игрок, а other.pair — пара этому порталу, куда игрок будет телепортироваться при нажатии на клавишу "E".

Запускаем и смотрим результат.

Ускоряющая платформа и платформа для прыжков

Создадим объект oJumpPlatform, унаследуем его от oSolid, а также привяжем к нему какой-нибудь спрайт, в моем случае — синий квадрат 64x64.

Немного поменяем код в событии Step объекта oPlayer, а именно в том месте, где игрок попиксельно двигается по вертикали:

. . . else { while (!place_meeting(x, y + sign(dy), oSolid)) y += sign(dy); if (place_meeting(x, y + sign(dy), oJumpPlatform)) dy = jumpImpulse * 1.5 * sign(dy); else dy = 0; } . . .

Здесь дополнительно осуществляется проверка, находится ли oPlayer вплотную к oJumpPlatform или нет. Если да, то он отталкивается от платформы, но в полтора раза сильнее, чем при обычном прыжке, при чем отталкивание происходит не только тогда, когда игрок прыгает на платформу, но и когда ударяется об нее сверху.

Создадим еще один объект, назовем его oRunPlatform, также унаследуем от oSolid и привяжем к нему спрайт, в моем случае — оранжевый квадрат 64x64.

В событии Create объекта oPlayer объявим переменную dxBoost — число, на которое будет умножаться dx. Оно будет равно 1.5, когда игрок стоит на ускоряющей платформе, и 1 — когда не стоит.

Добавим выделенный участок кода в событии Step объекта oPlayer. Он должен располагаться между уже имеющимися строками кода onGround = place_meeting(x, y + 1, oSolid); и xDir = -keyboard_check(ord("A")) + keyboard_check(ord("D"));:

. . . if (onGround) { if (place_meeting(x, y + 1, oRunPlatform)) dxBoost = 1.5; else dxBoost = 1.0; } . . .

dxBoost не обязательно должна быть равна 1.5, можно сделать это значение равным 2, тогда игрок будет ускоряться ровно в 2 раза.

Еще необходимо немного изменить код для обработки столкновений по горизонтали:

. . . if (!place_meeting(x + dx, y, oSolid)) //это удаляем if (!place_meeting(x + (dx * dxBoost), y, oSolid)) //и заменяем на это x += dx; //и это удаляем x += dx * dxBoost; //заменяем на это . . .
Возможно, здесь разница не так заметна, но она есть

Заключение

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

Скачать исходники можно здесь или здесь.

1818
10 комментариев