Программирование игр в GameMaker

Этот курс предназначен для начинающих разработчиков, желающих освоить создание 2D-игр с использованием движка GameMaker и языка GML. Вы пройдете путь от знакомства с интерфейсом до сборки и экспорта вашего первого игрового проекта.

1. Знакомство с GameMaker: Интерфейс, ресурсы и создание первого проекта

Знакомство с GameMaker: Интерфейс, ресурсы и создание первого проекта

Добро пожаловать в курс «Программирование игр в GameMaker». Это первая статья, и наша цель сегодня — не просто открыть программу, а понять философию этого движка, разобраться в его интерфейсе и создать свой первый, пусть и маленький, но работающий проект.

GameMaker — это один из самых популярных движков для создания 2D-игр. На нем были созданы такие хиты, как Undertale, Hyper Light Drifter и Katana ZERO. Его главная сила заключается в низком пороге входа и огромных возможностях для профессионалов.

Что такое GameMaker?

GameMaker (ранее GameMaker Studio 2) — это интегрированная среда разработки (IDE). Это означает, что всё необходимое для создания игры — редактор кода, редактор изображений, редактор уровней и звука — находится в одной программе.

В основе движка лежит событийно-ориентированное программирование. Это значит, что логика игры строится по принципу: «Если произошло событие А (нажата клавиша, столкновение, таймер), то выполнить действие Б».

Для написания логики используется язык GML (GameMaker Language). Он похож на C++ и JavaScript, но адаптирован специально для игр. В этом курсе мы будем изучать именно GML Code, так как он дает максимальный контроль над игрой.

Первый запуск и Стартовая страница

При запуске GameMaker вас встречает стартовое окно. Здесь вы можете увидеть последние новости, туториалы и список ваших проектов. Чтобы начать, нам нужно нажать кнопку New (Новый), выбрать тип проекта Game и шаблон Blank Game (Пустой проект). Назовем его MyFirstGame.

Обзор интерфейса: Ваше рабочее место

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

!Схема интерфейса GameMaker с выделенными ключевыми зонами: Браузером ресурсов, Рабочим пространством и окном Вывода.

1. Asset Browser (Браузер ресурсов)

Обычно он находится справа. Это «шкаф», где лежат все файлы вашей игры. Всё, что есть в игре — картинки, звуки, скрипты, уровни — живет здесь. Если ресурса нет в Asset Browser, его нет в игре.

2. Workspace (Рабочее пространство)

Это центральная и самая большая часть экрана. Здесь вы будете проводить 90% времени. Это бесконечный «стол», на котором вы раскладываете открытые окна редакторов: код объекта, настройки спрайта или карту уровня. Вы можете перемещаться по этому столу, зажимая колесико мыши.

3. Room Editor (Редактор комнат)

В GameMaker любой уровень, меню или экран называется Room (Комната). При создании проекта автоматически создается Room1. Это ваш холст, куда вы будете помещать объекты.

Ключевые понятия: Спрайты, Объекты и Комнаты

Чтобы создать игру, нужно понять «Святую Троицу» GameMaker. Без понимания разницы между этими элементами двигаться дальше невозможно.

Спрайт (Sprite)

Спрайт — это просто картинка. Это визуальная оболочка. Спрайт не умеет думать, двигаться или сталкиваться. Это просто «костюм», который можно надеть. В Asset Browser спрайты обычно имеют префикс spr_ (например, spr_player).

Объект (Object)

Объект — это «мозг» и сущность игры. Именно объект содержит программный код. Объект может не иметь картинки (быть невидимым контроллером) или использовать спрайт для отображения. В Asset Browser объекты именуют с префиксом obj_ (например, obj_player).

> Важное правило: Вы не можете поместить Спрайт прямо в Комнату как игрового персонажа. Вы должны создать Объект, назначить ему Спрайт, и только потом поместить Объект в Комнату.

Экземпляр (Instance)

Это понятие часто путает новичков. Объект — это чертеж (класс). Экземпляр — это конкретная копия этого чертежа, помещенная в комнату.

Представьте, что obj_enemy — это чертеж робота на бумаге. А 10 роботов, стоящих на уровне — это 10 экземпляров (instances) этого объекта. Изменяя код в Объекте, вы меняете поведение всех его Экземпляров.

Координатная система

Прежде чем мы заставим что-то двигаться, нужно понять, как GameMaker видит пространство. Это чистая математика, но очень простая.

!Иллюстрация координатной системы, где начало отсчета находится в левом верхнем углу экрана.

В школе нас учили, что ось направлена вверх. В программировании 2D-игр (и в обработке изображений вообще) ось почти всегда направлена вниз.

* Точка (0, 0) — левый верхний угол комнаты. * X увеличивается вправо. * Y увеличивается вниз.

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

Формула перемещения выглядит так:

где — новая координата по горизонтали, — текущая координата, а — скорость (количество пикселей за кадр).

Создание первого проекта: «Движущийся квадрат»

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

Шаг 1: Создание Спрайта

  • В Asset Browser нажмите правой кнопкой мыши (ПКМ) на папку Sprites.
  • Выберите Create -> Sprite.
  • Назовите его spr_box.
  • В открывшемся редакторе нажмите Edit Image.
  • Используя инструмент заливки, закрасьте квадрат любым цветом.
  • Закройте редактор изображения.
  • Шаг 2: Создание Объекта

  • В Asset Browser нажмите ПКМ на папку Objects.
  • Выберите Create -> Object.
  • Назовите его obj_box.
  • В окне объекта найдите поле Sprite (там сейчас написано No Sprite). Нажмите на него и выберите наш spr_box.
  • Теперь у нашего «мозга» есть «тело».

    Шаг 3: Программирование (События)

    Теперь самое интересное. Окно объекта имеет панель Events (События). Это список ситуаций, на которые объект должен реагировать.

    Нам нужны два основных события:

  • Create (Создание) — срабатывает один раз, когда объект появляется в мире. Здесь обычно задают начальные переменные (жизни, скорость).
  • Step (Шаг) — срабатывает каждый кадр игры (обычно 60 раз в секунду). Здесь пишется основная логика движения и проверок.
  • Добавим событие Create:

  • Нажмите кнопку Add Event -> Create.
  • Откроется окно редактора кода. Напишем там:
  • Здесь мы создали переменную move_speed и присвоили ей значение 4.

    Добавим событие Step:

  • Нажмите Add Event -> Step -> Step.
  • Напишем код движения:
  • Что здесь происходит? Каждый кадр (60 раз в секунду) мы берем текущую координату нашего объекта и прибавляем к ней значение переменной move_speed.

    Математически это выражается так:

    где — координата в следующем кадре, — координата в текущем кадре, а — наше смещение (скорость).

    Шаг 4: Размещение в Комнате

  • В Asset Browser откройте папку Rooms и дважды кликните по Room1.
  • Слева от редактора комнаты выберите слой Instances (это важно, объекты живут на слое Instances).
  • Перетащите obj_box из Asset Browser прямо на поле комнаты.
  • Шаг 5: Запуск

    Нажмите клавишу F5 или кнопку Play (зеленый треугольник) в верхней панели. Игра скомпилируется и запустится. Вы должны увидеть, как ваш квадрат уплывает вправо.

    Резюме

    Поздравляю! Вы только что прошли полный цикл разработки: от создания ресурсов до написания кода и тестирования. Мы узнали, что: * Asset Browser — это библиотека файлов. * Спрайт — это картинка, а Объект — это код. * Координата Y растет вниз. * Код выполняется внутри Событий (Events).

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

    2. Основы языка GML: Переменные, функции и управляющие конструкции

    Основы языка GML: Переменные, функции и управляющие конструкции

    В предыдущей статье мы познакомились с интерфейсом GameMaker и даже заставили квадрат двигаться, написав одну строчку кода. Но чтобы создать полноценную игру, одной строчки недостаточно. Нам нужно, чтобы игра запоминала количество жизней, реагировала на нажатия клавиш и принимала решения (например, «если здоровье равно нулю, игра окончена»).

    Сегодня мы погрузимся в GML (GameMaker Language). Мы разберем фундамент любого программирования: переменные, функции и условия. Это те самые «кирпичики», из которых строится логика любой игры, от Tetris до Elden Ring.

    Переменные: Память игры

    Представьте, что вы играете в RPG. У вашего героя есть имя, уровень здоровья, количество золота и сила удара. Где компьютер хранит эти числа? В переменных.

    Переменная — это именованная ячейка памяти, в которой хранится значение. Вы можете создать переменную, дать ей имя (например, hp) и положить в нее число (например, 100). Позже вы можете прочитать это число или изменить его.

    Типы данных

    В GML переменные могут хранить разные типы данных. Самые важные для нас сейчас:

    * Real (Числа): Любые числа, целые или дробные. Пример: 10, -5, 3.14. * String (Строки): Текст. Всегда заключается в кавычки. Пример: "Player 1", "Game Over". * Boolean (Булевы значения): Логический тип, который может быть только истиной (true) или ложью (false). Это используется для переключателей (например, is_dead = false).

    Область видимости переменных

    Это одна из самых важных тем в GameMaker. То, как вы объявите переменную, определяет, кто сможет её видеть и как долго она будет существовать.

    !Визуализация иерархии переменных: локальные живут только в моменте, переменные экземпляра — внутри объекта, глобальные — во всей игре.

    #### 1. Переменные экземпляра (Instance Variables)

    Это стандартный тип переменных. Если вы просто напишете в событии Create:

    ...то эти переменные будут принадлежать конкретному экземпляру объекта (например, конкретному врагу). Они будут существовать, пока жив этот враг. Другие объекты могут получить к ним доступ, если обратятся к этому экземпляру.

    #### 2. Локальные переменные (Local Variables)

    Они объявляются с ключевым словом var. Эти переменные существуют только в том куске кода (событии или скрипте), где они созданы, и исчезают сразу после завершения этого кода.

    Используйте var для временных вычислений, чтобы не засорять память.

    #### 3. Глобальные переменные (Global Variables)

    Они принадлежат не объекту, а всей игре. Они доступны из любого места и существуют, пока игра запущена. Объявляются через префикс global..

    Если вы перейдете на следующий уровень (в другую Комнату), переменные экземпляра исчезнут, а global.score останется.

    Функции: Глаголы языка GML

    Если переменные — это существительные (информация), то функции — это глаголы (действия). Функция — это готовый блок кода, который выполняет определенную задачу.

    GameMaker содержит тысячи встроенных функций. Вызов функции выглядит так:

    Аргументы — это данные, которые мы передаем функции, чтобы она знала, с чем работать. Некоторые функции требуют аргументов, некоторые — нет.

    Примеры: * instance_destroy() — уничтожает экземпляр, в коде которого написана эта функция (аргументы не нужны). * random_range(1, 10) — возвращает случайное число от 1 до 10 (нужны два аргумента: минимум и максимум). * draw_sprite(spr_player, 0, x, y) — рисует спрайт в заданных координатах.

    Возвращаемые значения

    Многие функции не просто что-то делают, но и возвращают результат. Представьте, что вы просите повара (функцию) приготовить пиццу. Вы даете ему продукты (аргументы), а он возвращает вам готовую пиццу (результат).

    Пример использования результата:

    Управляющие конструкции: Логика игры

    Чтобы игра была интерактивной, она должна уметь принимать решения. Для этого используются условные операторы.

    Оператор if (Если)

    Это главный инструмент логики. Конструкция выглядит так:

    Блок else (иначе) не обязателен. Вы можете использовать только if.

    Операторы сравнения

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

    * == — равно (Обратите внимание: два знака равенства для сравнения, один = для присваивания значения). * != — не равно. * > — больше. * < — меньше. * >= — больше или равно. * <= — меньше или равно.

    Пример логики здоровья:

    Логические операторы

    Иногда нужно проверить сразу несколько условий. Например, «Если игрок нажал пробел И он стоит на земле».

    * && (или and) — логическое И. Оба условия должны быть истинными. * || (или or) — логическое ИЛИ. Хотя бы одно условие должно быть истинным. * ! (или not) — логическое НЕ. Инвертирует значение (превращает true в false и наоборот).

    Пример сложного условия:

    Практика: Управление персонажем

    Давайте вернемся к нашему проекту из прошлой статьи. У нас был квадрат, который просто улетал вправо. Давайте сделаем его управляемым.

    Откройте объект obj_box и перейдите в событие Step. Удалите старый код и напишите следующий:

    Разбор математики движения

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

    Формула изменения координаты выглядит так:

    где — новая координата по вертикали, — текущая координата, а — скорость движения (в нашем коде это переменная spd).

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

    Циклы (Loops)

    Иногда нам нужно выполнить одно и то же действие много раз подряд. Например, создать 10 врагов или проверить столкновение со всеми стенами вокруг. Для этого существуют циклы.

    Самый простой цикл в GML — это repeat.

    Также существуют циклы while (выполнять, пока условие истинно) и for (цикл со счетчиком), но они сложнее, и мы разберем их, когда будем создавать систему инвентаря или процедурную генерацию уровней.

    Резюме

    Сегодня мы превратили GML из набора непонятных символов в инструмент управления игрой. Мы узнали:

  • Переменные хранят данные. var — для временных данных, обычные переменные — для свойств объекта, global — для всей игры.
  • Функции выполняют действия. Они могут принимать аргументы и возвращать ответы.
  • Условия (if) позволяют игре «думать» и реагировать на действия игрока.
  • Координатная математика требует внимательности с осью (вверх — это минус).
  • В следующем уроке мы разберем Спрайты и Анимацию: научим наш квадрат не просто скользить, а поворачиваться, менять кадры и выглядеть живым.

    3. Архитектура игры: Работа со спрайтами, объектами и событиями

    Архитектура игры: Работа со спрайтами, объектами и событиями

    Мы уже научились создавать проект, писать первые переменные и заставлять квадрат двигаться по экрану. Но квадрат — это не герой, а просто геометрическая фигура. Чтобы создать ощущение игры, нам нужно вдохнуть жизнь в наши объекты: научить их менять внешний вид, анимироваться и взаимодействовать друг с другом по сложным правилам.

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

    Анатомия Спрайта

    В первой статье мы сказали, что спрайт — это картинка. Это правда, но не вся. Спрайт в GameMaker — это сложный ресурс, обладающий свойствами, которые критически важны для программирования.

    Точка привязки (Origin Point)

    Когда вы говорите объекту x = 100, какая именно часть картинки окажется в координате 100? Левый верхний угол? Центр? Пятка персонажа?

    За это отвечает Origin Point (Точка привязки). Это «центр масс» спрайта.

    !Сравнение расположения точки привязки: слева вверху и по центру.

    * Top Left (0, 0): Стандарт для интерфейса и тайлов. Координаты объекта указывают на левый верхний угол картинки. * Middle Centre: Стандарт для персонажей и пуль. Это позволяет легко поворачивать объект вокруг своей оси и корректно отражать его по горизонтали. * Bottom Centre: Часто используется в платформерах и RPG с видом сверху, чтобы координаты объекта соответствовали точке, где ноги касаются земли.

    > Если ваш персонаж при повороте «скачет» по экрану или застревает в стенах, в 99% случаев проблема в неправильно выставленном Origin Point.

    Анимация и кадры

    Спрайт может состоять из нескольких картинок — суб-изображений (sub-images) или кадров. GameMaker автоматически проигрывает их по кругу.

    Скорость воспроизведения регулируется в редакторе спрайта (параметр FPS), но мы можем управлять ею и через код, используя встроенные переменные:

    * image_speed — множитель скорости анимации. 1 — нормальная скорость, 0 — пауза, -1 — обратное воспроизведение. * image_index — номер текущего кадра. Мы можем принудительно установить image_index = 0, чтобы сбросить анимацию в начало.

    Управление внешним видом через код

    Объект не приклеен к одному спрайту навсегда. Главная фишка GameMaker — возможность менять «костюм» объекта на лету.

    Допустим, у нас есть три спрайта:

  • spr_player_idle (стоит)
  • spr_player_run (бежит)
  • spr_player_jump (прыгает)
  • Чтобы сменить анимацию, мы используем переменную sprite_index.

    Пример кода в событии Step:

    Обратите внимание на image_xscale. Эта переменная отвечает за масштаб по горизонтали. Если установить её в -1, спрайт зеркально отразится. Это избавляет нас от необходимости рисовать отдельные спрайты для бега влево.

    Глубина и порядок отрисовки (Depth)

    В 2D-играх нет настоящей оси Z, но есть понятие «глубины» (Depth). GameMaker рисует объекты в определенном порядке:

  • Объекты с большей глубиной (например, 100) рисуются первыми (задний план).
  • Объекты с меньшей глубиной (например, -100) рисуются поверх них.
  • Представьте, что вы кладете листы бумаги на стол. Лист с глубиной 100 кладется первым. Лист с глубиной 0 кладется на него сверху.

    Мы можем менять глубину динамически:

    Этот простой трюк часто используется в Top-Down играх (вид сверху). Чем ниже персонаж на экране (чем больше y), тем меньше становится его depth, и тем «ближе» к камере он рисуется. Это позволяет персонажу корректно перекрывать деревья и стены, проходя перед ними или за ними.

    Жизненный цикл событий (Event Loop)

    Новички часто путаются, когда именно выполняется их код. GameMaker выполняет код не хаотично, а в строгой последовательности каждый кадр.

    !Упрощенная схема игрового цикла (Game Loop) одного кадра.

    1. События Step (Шаг)

    Это «мозг» игры. Здесь происходят вычисления.

    * Begin Step: Срабатывает в начале кадра. Хорошо подходит для сброса переменных перед расчетами. * Step: Основное событие. Здесь мы пишем движение, проверки клавиш и столкновения. End Step: Срабатывает после того, как все объекты выполнили свой основной Step. Идеально для камеры (камера должна двигаться за игроком только после* того, как игрок закончил свое движение).

    2. Событие Draw (Отрисовка)

    Это «глаза» игры. Здесь происходит вывод графики на экран.

    > Важное правило: Никогда не пишите игровую логику (движение, начисление очков) в событии Draw. И наоборот, никогда не пытайтесь рисовать текст или спрайты в событии Step.

    По умолчанию GameMaker сам рисует назначенный спрайт. Но если вы добавите событие Draw в объект, автоматическая отрисовка отключится! Вам придется вручную написать:

    Математика в архитектуре: Расстояние

    В играх нам постоянно нужно знать расстояние между объектами. Например: «Если враг ближе 200 пикселей, он начинает атаку».

    Для этого используется теорема Пифагора, так как расстояние между двумя точками на плоскости — это гипотенуза прямоугольного треугольника.

    Формула расстояния между двумя точками и выглядит так:

    Где: * — искомое расстояние (distance). * — координаты первого объекта (например, игрока). * — координаты второго объекта (например, врага). * — квадратный корень.

    В GML нам не нужно писать эту формулу вручную каждый раз. Разработчики движка уже внедрили её в функцию point_distance.

    Пример использования:

    Маски коллизий (Collision Mask)

    Последний важный элемент архитектуры спрайта — это маска столкновений. Это зона, которая считается «твердой».

    Часто спрайт может быть большим (например, с развевающимся плащом), но маску делают маленькой (только ноги и торс). Это делается для честности игры: игрока не должно убивать, если пуля задела кончик его плаща.

    В редакторе спрайта вы можете настроить Collision Mask: * Automatic: Маска покрывает все непрозрачные пиксели. * Manual: Вы сами рисуете прямоугольник или эллипс, который будет считаться физическим телом объекта.

    Для проверки столкновений в коде мы часто используем функцию place_meeting(x, y, obj_wall). Она виртуально помещает объект в указанные координаты и проверяет, пересекается ли его маска с маской стены.

    Резюме

    Сегодня мы разобрали, как устроены объекты изнутри:

  • Origin Point определяет центр вращения и позиционирования спрайта.
  • Переменные sprite_index и image_xscale позволяют управлять анимацией и поворотом.
  • Depth определяет, кто кого перекрывает.
  • Игровой цикл делит кадр на фазу логики (Step) и фазу рисования (Draw).
  • Функция point_distance помогает вычислять дистанцию между объектами, используя математику координат.
  • В следующей статье мы применим эти знания на практике и создадим полноценную систему стрельбы и уничтожения врагов.

    4. Геймплей: Реализация движения, коллизий и игровой физики

    Геймплей: Реализация движения, коллизий и игровой физики

    В предыдущих статьях мы научились создавать спрайты, объекты и даже заставили их двигаться. Однако наше движение было «призрачным»: персонаж проходил сквозь стены, улетал за пределы экрана и не подчинялся законам гравитации. Это не похоже на игру.

    Сегодня мы превратим наш «летающий квадрат» в полноценного персонажа платформера. Мы напишем физический движок с нуля, разберем алгоритмы столкновений (коллизий) и научимся применять математику для создания ощущения веса и инерции.

    Подготовка: Переменные физики

    Чтобы управлять физикой, нам нужно отказаться от прямого изменения x и y при нажатии клавиш. Вместо этого мы будем управлять скоростью, а координаты будут меняться в зависимости от неё.

    В событии Create нашего игрока (obj_player) создадим переменные, которые станут основой нашей физической модели:

    Обратите внимание: мы не используем встроенные переменные GameMaker hspeed и vspeed. Использование собственных переменных (hsp, vsp) дает нам полный контроль над кодом и позволяет избежать конфликтов с автоматическими системами движка.

    Вектор движения и ввод

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

    Как работает формула move?

    Давайте разберем математику строки var move = key_right - key_left;.

    * Если нажата только правая клавиша: . Мы движемся вправо. * Если нажата только левая клавиша: . Мы движемся влево. * Если нажаты обе или ни одной: или . Мы стоим.

    Умножая это значение на walksp (4), мы получаем hsp, равное 4, -4 или 0.

    Гравитация: Падение вниз

    Гравитация — это постоянное ускорение, направленное вниз. В каждом кадре мы должны увеличивать вертикальную скорость персонажа.

    Добавим в Step:

    Математически это выражается формулой равноускоренного движения:

    Где — новая скорость, — текущая скорость, а — ускорение (в нашем случае переменная grv). Поскольку ось Y направлена вниз, прибавление положительного числа заставляет объект падать быстрее с каждым кадром.

    Теория коллизий: Предсказание будущего

    Самая сложная часть платформера — это столкновения со стенами. Новички часто совершают ошибку: сначала перемещают персонажа, а потом проверяют, не застрял ли он. Это приводит к тому, что герой «влипает» в стены.

    Правильный подход — предиктивный (предсказательный). Мы должны проверить: «Если я перемещусь на текущую скорость, врежусь ли я в стену?».

    !Визуализация предиктивной проверки столкновений: мы проверяем место, куда собираемся шагнуть, до того, как сделать шаг.

    Для этого мы используем функцию place_meeting(x, y, obj). Она виртуально помещает объект в заданные координаты и возвращает true, если там есть коллизия.

    Реализация горизонтальной коллизии

    Нам нужен объект стены. Создайте спрайт квадрата, назовите его spr_wall, создайте объект obj_wall и расставьте эти стены в комнате, сделав пол и препятствия.

    Теперь пишем код в Step игрока (после расчета hsp, но до изменения x):

    Разбор алгоритма

  • Проверка: place_meeting(x + hsp, ...) проверяет, свободно ли место, куда мы хотим попасть.
  • Цикл while: Если место занято, мы не можем сделать полный шаг. Но мы не хотим останавливаться за 3 пикселя до стены. Мы хотим коснуться её. Цикл while работает так: «Пока на 1 пиксель впереди свободно — делай микро-шаг».
  • Функция sign(): Это важная математическая функция.
  • Где — результат функции, который может быть равен только трем значениям: (если число положительное), (если отрицательное) и (если ноль). Это позволяет нам двигаться ровно на 1 пиксель в нужную сторону, независимо от того, равна наша скорость 4, 10 или 100.

    Реализация вертикальной коллизии

    Логика абсолютно идентична горизонтальной, только работаем с осью Y и переменной vsp.

    Этот код обрабатывает и падение на пол, и удар головой об потолок. Когда персонаж падает на пол, place_meeting срабатывает, цикл доводит его до касания земли, и vsp становится 0 (падение прекращается).

    Прыжок

    Прыжок возможен только тогда, когда мы стоим на земле. Как игра поймет, что мы на земле? Очень просто: если на 1 пиксель ниже нас есть стена.

    Добавим код прыжка после расчета ввода, но до коллизий:

    Почему -7? Вспоминаем координатную сетку: Y растет вниз. Чтобы подлететь вверх, нужно резко уменьшить Y, то есть придать отрицательную скорость.

    Итоговый код события Step

    Вот как выглядит полный код физики платформера, который вы должны поместить в событие Step объекта obj_player:

    Анимация в воздухе

    В прошлой статье мы меняли спрайты для бега. Теперь у нас есть состояние прыжка и падения. Мы можем улучшить визуализацию:

    Здесь мы проверяем: если под ногами нет стены (мы в воздухе), включаем спрайт прыжка. Если vsp > 0 (мы падаем), показываем второй кадр прыжка. Если vsp < 0 (мы летим вверх), показываем первый кадр.

    Резюме

    Поздравляю! Вы только что написали свой первый физический движок. Это не просто набор команд, это система, которая моделирует реальный мир: гравитацию, твердость объектов и инерцию.

    Мы узнали, что: * Коллизии нужно предсказывать: проверяем место x + hsp до того, как туда переместиться. * Функция sign() незаменима для попиксельного приближения к препятствию. * Гравитация — это просто постоянное прибавление числа к вертикальной скорости.

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

    5. Финальные штрихи: Создание интерфейса, работа со звуком и экспорт игры

    Финальные штрихи: Создание интерфейса, работа со звуком и экспорт игры

    Мы проделали огромный путь. У нас есть управляемый персонаж, физика прыжков, коллизии со стенами и понимание того, как работает код. Но если вы покажете этот проект другу, он скажет: «Это просто квадрат, прыгающий по квадратам». Чтобы превратить прототип в полноценный продукт, нам нужно добавить «сочность» (juice), обратную связь и возможность запустить игру без установки GameMaker.

    В этой финальной статье курса мы разберем три критически важных аспекта: создание пользовательского интерфейса (HUD), добавление звуковых эффектов и экспорт готового файла игры.

    Пользовательский интерфейс (GUI)

    В предыдущих уроках мы использовали событие Draw для отрисовки спрайтов. Но если мы попытаемся нарисовать счетчик жизней в событии Draw обычного объекта, он останется висеть в конкретной точке комнаты. Когда камера сдвинется, счетчик уедет за край экрана.

    Для интерфейса в GameMaker существует специальное событие: Draw GUI.

    !Схема различия между слоем игровой комнаты и слоем интерфейса (GUI).

    Особенности Draw GUI

  • Независимость от камеры: Координата в этом событии — это всегда левый верхний угол экрана (или окна игры), а не игровой комнаты.
  • Поверх всего: Все, что нарисовано в Draw GUI, автоматически рисуется поверх обычных спрайтов.
  • Создание контроллера интерфейса

    Обычно для интерфейса создают отдельный объект-менеджер, который не имеет спрайта. Назовем его obj_game_control.

  • Создайте объект obj_game_control.
  • Добавьте событие Draw GUI.
  • Напишем код для вывода текста:
  • Обратите внимание на функцию string(). GameMaker не позволяет просто сложить текст "Health: " и число global.hp. Функция string() превращает число в текст, чтобы их можно было склеить.

    Рисование полоски здоровья (Healthbar)

    Вместо скучного текста лучше нарисовать полоску. В GML есть встроенная функция для этого, которая идеально подходит для прототипов.

    Эта функция автоматически рассчитывает длину цветной полосы в зависимости от значения переменной global.hp (ожидается значение от 0 до 100).

    Если вы хотите сделать свою кастомную полоску здоровья из спрайтов, вам понадобится математика пропорций.

    Где: * — текущая ширина полоски, которую мы должны нарисовать. * — полная ширина спрайта полоски (в пикселях). * — текущее здоровье персонажа. * — максимальное здоровье персонажа.

    В коде это реализуется через функцию draw_sprite_part или изменение image_xscale.

    Камера и Viewports

    Наша комната может быть огромной, но экран монитора ограничен. Чтобы игрок видел персонажа, камера должна следовать за ним.

    В GameMaker это настраивается без кода (хотя кодом тоже можно).

  • Откройте Room Editor (вашу комнату).
  • В свойствах слева найдите раздел Viewports and Cameras.
  • Поставьте галочку Enable Viewports (Включить видовые экраны).
  • Раскройте Viewport 0 и поставьте галочку Visible (Видим).
  • Теперь настроим два важных параметра:

    * Camera Properties (Свойства камеры): Это размер «объектива». Сколько игрового мира мы видим. Например, . * Viewport Properties (Свойства порта): Это размер окна на мониторе. Если поставить здесь , то картинка с камеры увеличится в 2 раза (пиксели станут крупнее).

    Слежение за объектом (Object Following): В поле Object Following выберите вашего игрока obj_player. Теперь камера будет автоматически центрироваться на нем.

    Параметры Horizontal Border и Vertical Border определяют «мертвую зону». Если поставить их равными половине ширины/высоты камеры, персонаж всегда будет строго по центру.

    Работа со звуком

    Звук — это 50% атмосферы игры. В GameMaker аудио-движок прост, но мощен.

    Импорт звуков

  • В Asset Browser создайте папку Sounds.
  • Перетащите туда ваши файлы .wav или .mp3.
  • Назовите их с префиксом snd_ (например, snd_jump, snd_music).
  • Настройка звукового файла

    Дважды кликните по звуку. Важно правильно выставить настройки: * Для коротких эффектов (выстрел, прыжок) оставьте Uncompressed (Not Streamed). * Для фоновой музыки обязательно выберите Compressed - Streamed. Это сэкономит оперативную память, так как музыка будет читаться с диска, а не загружаться целиком в память.

    Воспроизведение звуков

    Вернемся к коду игрока obj_player. В момент прыжка добавим звук.

    Разберем аргументы функции audio_play_sound:

  • Sound ID: Имя ресурса (snd_jump).
  • Priority (Приоритет): Число от 0 до 100. Если каналов звука не хватит, звуки с низким приоритетом будут заглушены. У музыки обычно ставят низкий приоритет (0-10), у важных эффектов — высокий (50-100).
  • Loop (Зацикливание): true для музыки, false для эффектов.
  • Для запуска фоновой музыки лучше всего использовать событие Create в объекте-контроллере obj_game_control:

    Управление состоянием игры

    Игра должна уметь перезапускаться. Допустим, если персонаж упал в пропасть.

    В событии Step игрока добавим проверку:

    Также полезно добавить горячую клавишу для полного перезапуска игры (для тестов):

    Экспорт проекта

    Когда игра готова, вы не будете отправлять друзьям файл проекта .yyp. Им нужен .exe файл.

    Компиляция

    GameMaker переводит ваш GML-код в машинный код (или C++, в зависимости от типа лицензии и настроек).

  • В правом верхнем углу IDE найдите кнопку Create Executable (иконка пакета или архива).
  • Выберите формат: Zip (архив с игрой) или Installer (установщик).
  • Совет:* Для небольших игр лучше выбирать Zip. Игроку проще распаковать архив и играть, чем устанавливать программу.
  • Выберите папку для сохранения и имя файла.
  • Нажмите Save.
  • Процесс компиляции займет некоторое время. В окне Output вы увидите лог сборки. Если ошибок нет, откроется папка с готовой игрой.

    Заключение курса

    Поздравляю! Вы прошли путь от пустого экрана до готового исполняемого файла.

    Мы изучили:

  • Интерфейс GameMaker и структуру ресурсов.
  • GML: Переменные, условия, циклы и функции.
  • Архитектуру: Разделение логики (Объекты) и графики (Спрайты).
  • Физику: Векторы движения, гравитацию и предиктивные коллизии.
  • Полировку: Интерфейс, звук и камеру.
  • GameMaker — это инструмент с бесконечным потенциалом. То, что мы создали — это фундамент. Дальше вы можете изучать массивы для инвентаря, структуры данных для диалогов, шейдеры для красивых эффектов и сетевой код для мультиплеера.

    Главный совет начинающему разработчику: заканчивайте игры. Лучше маленькая, но готовая игра, выложенная в интернет, чем «проект мечты», который никогда не покинет ваш жесткий диск. Удачи в разработке!