GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами

Привет! Это вторая часть урока.
Первая:
GameMaker Studio 2. Урок 1. Знакомство

Сегодня у нас много матчасти и не очень много кода.

Конкретизация разработки.

Как было сказано в прошлом посте, игра, которая будет сделана в ходе данных гайдов, будет относиться к жанру стратегий, а в качестве источников для "вдохновения" у нас - "Oxygen Not Included" и "Rimworld". Теперь же конкретно поговорим с вами о том, что в игре должно быть реализовано, по пунктам.

-) Персонажи.

--) Персонаж - игровой "объект", способный перемещаться по игровому миру и взаимодействовать с ним. Делятся на подконтрольных и неподконтрольных игроку. Игрок НЕ имеет прямого управления над своими подопечными, кроме специального "боевого" режима.

--) Каждый персонаж должен иметь или уметь следующее:

---) Взаимодействовать с предметами, расположенными на карте: подбирать их в свой инвентарь или выкладывать; взаимодействовать с рабочими станциями; сражаться (наносить, получать урон).

---) Каждый персонаж смертен. Каждый персонаж должен иметь ряд характеристик, которые он будет пытаться "поддерживать" на должном уровне, чтобы не умереть и продолжать быть эффективным. Эти характеристики:

----) Сон

----) Голод

----) Настроение

---) Каждый персонаж уникален и должен отличаться от других. Черты, навыки с различными уровнями прокачки. Этот пункт может игнорироваться в случае, если это не подходит под конкретного персонажа.

-) Интерактивные объекты.

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

---) Пример: верстак для создания вещей; исследовательский стол для открытия новых вещей и пр.

-) Интерфейс.
--) Простой, понятный. Желательно, на русском языке.
--) Хотя бы минимально настраиваемый.


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

Сейчас - продолжаем изучать матчасть.

События отрисовки.

Матчасть.

Событие отрисовки добавляется на объект как и любое другое, через кнопку "Добавить событие (Add Event)".

Имеется два события:

-) Draw

--) Событие, которое отрисовывает объект в комнате.

-) Draw GUI.

--) Событие, которое отрисовывает объект на экране.

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Иными словами, событие отрисовки GUI позволяет нам закрепить на экране наш интерфейс и то, что мы хотим игроку показывать всегда. Draw - стандартная отрисовка.

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

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

ВАЖНО!

Если вы добавили событие отрисовки, то вам необходимо написать в коде следующую строку:

draw_self();

В противном случае, объект не будет отрисован.
Проделайте это сами. :)

Итак. Что мы можем делать в событиях отрисовки:
-) Отрисовка спрайтов:
--) draw_self() - отрисовывает спрайт текущего объекта с настройками по умолчанию.
--) draw_sprite_ext( название спрайта в обозревателе, номер изображения, x, y, x-масштабирование, y-масштабирование, поворот, цвет, прозрачность) - отрисовка спрайта "расширенная" - т.е. с настройками. Можно отрисовать любой спрайт, как и везде, где его нужно отдельно указывать.

--) draw_sprite_part(название спрайта в обозревателе, номер изображения, x координата левой верхней точки спрайта, y координата левой верхней точки спрайта, ширина, высота, x, y) - отрисовка части спрайта
--) draw_sprite_stretched(название спрайта в обозревателе, номер изображения, x, y, ширина, высота) - отрисовка спрайта с его "растяжением". Если у спрайта включить и настроить функцию Nine Slice (девять "срезов"), то можно создавать масштабируемые (с одинаковым разрешением, пропорциями и качеством по итогу) элементы интерфейса: окошки, кнопки, etc.

-) Отрисовка фигур:
--) draw_circle(x, y, радиус, заполнение (True/False)) - рисуем круг. Аналогичное есть для прямоугольника (rectangle), стрелки (arrow), эллипса (ellipse), линии (line).
--) draw_button(x, y, x2, y2, up) - Отрисовка кнопки. Где up - True или False, нажата кнопка или нет.

-) Настройки отрисовки.
--) ВАЖНО. Любые настройки отрисовки нужно проводить ПЕРЕД отрисовкой. Можно делать в любом событии, но для удобства лучше тут же.
--) draw_set_color(col) - устанавливаем цвет отрисовки. Базовые значения цветов начинаются с приписки "c_". Пример: c_black, c_red.
---) Для продвинутых - можно использовать HEX, как в CSS: #11CCFF как пример. Используется стандартная RGB система. Если заменить решётку на $, то система сменится на BBGGRR, т.е. наоборот.
--) draw_set_alpha(alpha) - прозрачность отрисовки
--) draw_set_font(font) - устанавливаем шрифт
--) draw_set_halign(halign) - Расположение текста по горизонтальной оси (fa_ left/center/right)
--) draw_set_valign(valign) - Расположение текста по горизонтальной оси (fa_ top/middle/bottom)

Это та часть, что касается кода и с которой мы с вами будем непосредственно работать. Можете держать как памятку у себя перед глазами, когда начнём писать код.

Коллизия


Коллизия - иначе говоря, столкновение объектов, происходит благодаря "маске" спрайта. Если спрайт - это картинка объекта, то маска - это "твёрдое тело", отвечающее за считывание столкновений.
Чтобы её посмотреть, откройте настройки спрайта и разверните пункт "Collision Mask"

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Хотя маска может иметь несколько форм, о которых будет написано ниже, устанавливается она исходя из четырёх позиций - левого верхнего и правого нижнего углов. Именно эта маска считывает столкновения, а не сам спрайт.

Mode - режим маски. Варианты:
- Автоматическая
- На всё изображение
- Ручная

Type - тип маски. Варианты:
- Прямоугольник
- Прямоугольник с поворотом
- Эллипс (работает медленнее)
- "Алмаз" (ромб) (работает медленнее)
- Предрасчет / Точный (медленнее) - ГМС постарается сам подстроить маску под форму объекта.
- Предрасчет / Точный по кадрам.

Мой совет:
Если игра небольшая, ставьте ручной режим и настраивайте сами те объекты, для которых это важно. Особенно те объекты, столкновение с которыми должно происходить только в определённой позиции (скажем, как в Стардью, сталкиваешься с основанием дерева, но не с его кроной).

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

Как работают скрипты.

Скрипт (функция) - именованный блок кода, выполняющий определённую задачу.
Все команды, которые мы использовали до этого, являются такими "скриптами". Иногда я буду называть их функциями, оба варианта правильные.

Создать скрипт просто. Для этого нажмите ПКМ по папке "Scripts" и выберете там "Script". Назовите его scrMove
У вас откроется следующее окно:

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

scrMove - название нашей функции. В круглых скобках мы в неё можем передавать аргументы. Аргумент - это переменная, которая используется только в функции, передаётся в неё при вызове и может иметь любое название. В скобках напишите spd - это будет как раз наша переменная скорости.
Вырежьте код движения из Step-события у игрока и вставьте в скрипт, а в Step-событии игрока напишите следующий код:
scrMove(player_speed);

Получится следующая картина:

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок
GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Как вы заметили, "x" и "y" у нас по прежнему работают. Это потому, что мы выполняем скрипт в объекте oPlayer: данные переменные подтягиваются из объекта автоматически.

Когда нужно применять скрипты?
-) Когда код, который мы пишем, нужно использовать несколько раз.
-) Когда код, который мы пишем, занимает много места, чтобы его было проще отладить.
-) Когда нам нужно получить какое-либо значение на основе каких-либо данных, так как скрипт может не просто выполнять код, но и возвращать значения.

Для того, чтобы скрипт вернул какое-то значение, нужно написать:

return название_переменной/значение.
Переменную можно написать только одну. Команда return прерывает выполнение скрипта. Переменную / возвращаемое значение можно не писать, тогда скрипт просто прервётся.
Конструкцию с прерыванием следует добавлять везде, где это может повлиять на игру, особенно её работоспособность.

Раньше скрипты выполнялись медленнее, чем код, написанный просто в объекте. Сейчас это не так (или, по крайней мере, не так критично).

Также стоит понимать, что создав объект "Скрипт", вы, по сути, создали просто файл для хранения кода. В одном скрипте может быть собрано сразу множество разных функций, отвечающих за выполнение одной задачи. При вызове обращаться нужно именно к имени функции.

Скрипт для отрисовки текста с обводкой.

Создаём новый скрипт и называем его scrOutlinedText
Нам понадобятся следующие аргументы:
-) xPos - позиция текста по X
-) yPos - позиция текста по y
-) col - цвет текста
-) outlineCol - цвет обводки
-) text - текст
-) curdepth - текущая "глубина" объекта.
-) Шрифт, которым будем рисовать.
-) Позиционирование по X
-) Позиционирование по Y

Общая схема работы скрипта:
1) Назначаем максимальную "глубину".
2) Рисуем текст цветом обводки.
3) Поверх рисуем текст нужным нам цветом, но с небольшим смещением.
4) Возвращаем глубину к первоначальным показателям.

Код:
https://pastebin.com/TahYZKc8
P.S.
Изначально код не мой, а честно стырен подсмотрен с интернета, но я в него добавил больше переменных для лучшей настройки и отрисовки. Фактически, значение глубины тоже можно передавать как аргумент, чтобы разный текст выводился по разному.

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Создание русского шрифта

Проверим, как работает скрипт.
Сначала мы создадим русский шрифт. Для этого найдём папку "Fonts", нажмём ПКМ и создадим "Font".
Выбирайте любой шрифт и размер, который хотите. Нам с вами нужна кнопка "Add", чтобы добавить диапазон с русским шрифтом.

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок
GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Здесь напишем 1040 to 1105, чтобы захватить весь русский алфавит, затем нажмём "Add Range".
Шрифт называйте на Ваше усмотрение. Я назову его: fontArialRusSmall

Теперь перейдём к объекту игрока. Создадим событие Draw GUI и напишем следующий код:
scrOutlinedText(10, 10, c_yellow, c_red, "Скорость: " + string(player_speed), depth, fontArialRusSmall, fa_left, fa_top)

Результат:

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Можете заменить c_yellow и c_red на любые цвета. Помните, что можно передавать цвета в HEX с помощью # и $ (в обратном порядке).

Скрипт для поиска значения в массиве:

Так как эту тему мы не проходили, заострять внимание не буду, но вдруг кому пригодится:
https://pastebin.com/1VTNg4Bp

function scrFindInArray(array, value)
{
if is_array(array)
{
for (var i = 0; i < array_length(array); i++)
{
if array[i] == value
{
return i
}
}
return noone
}
else
{
return noone
}
}
Работает просто, но встроенной функции подобного толка в GMS нет:
- Проверяет, что аргумент является массивом.
- Обходим массив и, если какое-то значение является его элементом, возвращаем индекс. Если же совпадений не было или аргумент не массив - возвращаем "noone" - в GML это значение равняется -4.
По сути, код можно и упростить, убрав проверку на то, что переданное значение является массивом, но с ней меньше шансов накосячить. :)

Переходы между комнатами. Создаём меню.

Наконец, с матчастью мы закончили. Приступим к тому, что создадим меню нашей игры.
Создаём новую комнату и обзываем её rmMainMenu. Затем нажмите на значок "домика", чтобы поменять стартовую комнату (ту, что отображается при запуске игры).

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Сделайте так, чтобы домик был напротив созданной комнаты.
Заметьте, что при создании новой комнаты у неё изменяются все настройки! Это важно.

Создадим в "Objects" папку "Меню", где создадим следующие объекты: "oMStart", "oMSettings", "oMExit", "oMMenu".
OMStart - кнопка для старта нашей игры.
OMSettings - кнопка для перехода в настройки игры.
oMExit - кнопка для выхода из игры
oMLoad - кнопка для загрузки игры
oMMenu - управляющий объект, который будет располагать наши кнопки.

Зайдём в комнату MainMenu и поставим там объект oMMenu.
Затем перейдём в код oMMenu и выберем событие создания (Create)

Там напишем следующий код:

buttons = [oMStart, oMLoad, oMSettings, oMExit]
Здесь мы поместили все наши кнопки в массив. Таким образом, мы можем обратиться к объекту-кнопке, используя название массива и квадратные скобки: 
buttons[0] - будет обращаться к первому элементу массива (oMStart)
Теперь нужно каждую из этих кнопок разместить. Но, чтобы правильно их разместить, сделаем на все кнопки один спрайт. Размер подбирайте под себя.

У каждого объекта создадим два события: Draw, которое оставим пустым, и Draw GUI, где напишем draw_self();
Там же напишем:
scrOutlinedText(x, y, c_white, c_black, "Здесь текст кнопки", depth, fontArialRusSmall, fa_center, fa_middle)
Где "Здесь текст кнопки" - заменить на нужное: "Начать игру", "Загрузить игру", "Настройки", "Выход"

Вернёмся в OMMenu.
Нажмите правой кнопкой мыши. Наведитесь на пункт "Code Snippets" и выберите пункт 5.
В данном меню расположены готовые шаблоны кода, а мы создали шаблон цикла.
Напишите следующий код:

for (var i = 0; i < array_length(buttons); ++i)

{

instance_create_layer(room_width / 2, room_height / 2 - 50 + sprite_get_height(sButton) / 2 + 100 * i, "Instances", buttons[i])

}

Этот код создаёт инстансы объектов, которые перечислены в нашем массиве, по центру комнаты, плавно опускаясь вниз. Не забудьте поставить Origin у спрайта кнопки по центру.
Координаты настраивайте под себя. Для этого изменяйте первые два аргумента (идут до "Instances".)
Скриншот:
GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Теперь нужно сделать отслеживание нашей мышки. Кнопку "Настройки" мы сделаем чуть позже. Пока перейдём к кнопке для выхода из игры.

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

dmxg = device_mouse_x_to_gui(0)
dmyg = device_mouse_y_to_gui(0)

ОК. Теперь мы отслеживаем нашу мышку относительно GUI. Нужно проверить, наведены ли мы на конкретный объект и если да - нарисовать поверх него полупрозрачный белый прямоугольник. Для этого есть команда:
instance_position(x, y, obj)

В x и y мы передадим переменные выше, а в качестве объекта напишем "self", чтобы проверять координаты нашего объекта.

Код:

if instance_position(dmxg, dmyg, self)
{
draw_set_color(c_white)
draw_set_alpha(0.15)
draw_rectangle(bbox_left, bbox_top, bbox_right, bbox_bottom, false)
draw_set_alpha(1)
}
Уже после этого пишем наш текст.
Теперь при наведении на кнопку "выхода" мы увидим, что она "активна".

Вырежем наши две переменные, добавим их в событие create. Теперь мы можем использовать эти переменные в любом коде этого объекта.

Теперь перейдём в событие step. Сюда также добавим наши две переменные. Теперь они будут постоянно обновляться.
Начнём настраивать логику работы.

Можете скопировать тот код, что мы писали выше, но удалить всё изнутри.
Нам нужно сделать проверку:
Если мы наведены на объект И нажата левая кнопка мыши - выйти из игры. То есть, немного её дополнить.

Для проверки нажатия кнопки левой мыши будем использовать команду:
mouse_check_button_pressed(mb_left)
Для выхода из игры:
game_end()

В итоге, в коде step будет следующий код:

dmxg = device_mouse_x_to_gui(0)
dmyg = device_mouse_y_to_gui(0)
if instance_position(dmxg, dmyg, self) and mouse_check_button_pressed(mb_left)
{
game_end()
}
Итого, если мы наведёмся на кнопку выхода - она подсветится. Нажмём - игра закроется.

Аналогичный код с подсветкой и проверкой просто скопируем в oMStart. В других кнопках логику работы в step пока не настраиваем на них, работаем с кнопкой начала игры.
Нужно внести одно изменение.

Вместо game_end() нам нужно написать код для смены уровня.
Для этого напишем:
room_goto(Room1)
Где Room1 - название комнаты, в которую вы хотите переместиться. Оно должно совпадать с названием комнаты в браузере ассетов.

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

Для этого нам придётся создать новый объект и назвать его oGameManager.
Разместим его в самой первой комнате и отметим у него чекбокс "Persistent"
Затем напишем у него в Step код:

Если индекс текущей комнаты != 0 и нажата ESC - деактивируем все инстансы, кроме текущего и переходим в меню.

if room != 0 and keyboard_check_pressed(vk_escape)
{
instance_deactivate_all(true)
room_goto(rmMainMenu)
}
Также отметим комнату с игроком как "Persistent".
Чтобы объекты в комнате, при возвращении, были активированы, немного дополним наш oGameManager. Для этого создадим у него событие "Room Start". 
GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

При старте комнаты, если эта комната не является меню, мы будем запускать все инстансы.

if room != 0
{
instance_activate_all()
}
Всё. Теперь мы можем спокойно выходить в меню из игры и возвращаться обратно при необходимости.

Реализация сложнее. О том, как работает Nine Slice.

Ниже будет приведена реализация меню с использованием функции Nine Slice, которая позволит нам делать кнопки других размеров.
Используя Nine Slice мы не сможем проверять, наведены ли мы сейчас на нужный нам объект. Также эта функция годится только для отрисовки типовых форм с типовым шрифтом. Если у вас спрайт кнопки идёт с текстом, то данная функция не подойдёт.
Чтобы отслеживать нажатия и наведение, нам необходимо проверять, находятся ли координаты мыши в нужной области. Для этого существует команда

point_in_rectangle(px, py, x1, y1, x2, y2)

Итак. Первый шаг - это убрать спрайт у каждой нашей кнопки.
Для этого откроем объект каждой кнопки, нажмём на выбор спрайта и выберем "None".

Шаг второй.
У каждой кнопки в событии Create мы пропишем:

width = 0;
height = 0;
При создании кнопок мы и так будем знать их x и y координаты, а ширину и высоту будем передавать.

Шаг третий
Нарисуем спрайт в виде одноцветного квадрата размером 9х9 пикселей.
Затем добавим ему две обводки разных цветов, каждая шириной в 1 пиксель.
Получим следующую картину:
GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Теперь перейдём в настройки спрайта.
Назовём его sButtonSlice.
Слева выберем и откроем пункт Nine Slice.

После чего поставим галочку "Activate Nine Slice".
Далее - смотрим на наш спрайт и настраиваем его, как показано на скриншоте ниже:

GameMaker Studio 2. Урок 2. События отрисовки. Коллизия. Как работают скрипты. Как подключить русский шрифт. Переходы между комнатами Разработка, Gamedev, Программирование, Инди, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок

Чтобы двигать фиолетовые полоски - достаточно на них навестись и зажать ЛКМ.
В правом окошке вы можете порастягивать данный спрайт, как хотите и посмотреть на итоговый результат.
Растягивающаяся рамка для кнопок готова!

Шаг четвертый.

Пропишем в Draw GUI отрисовку кнопки вместо draw_self():

draw_sprite_stretched(sButtonSlice, 0, x - width / 2, y - height / 2, width, height)

Таким образом, мы отрисовываем кнопку.

Шаг пятый.

Вернёмся в oMMenu, в Create, где немного допишем наш код.
Мы создадим переменную, которой будем присваивать значение ID только что созданного объекта. Затем, обращаясь к этой переменной, мы будем менять у данного объекта параметры: ширину и высоту.

buttons = [oMStart, oMLoad, oMSettings, oMExit]
var bwidth = 400
var bheight = 96
for (var i = 0; i < array_length(buttons); ++i)
{
inst = instance_create_layer(room_width / 2, room_height / 2 - 50 + 100 * i, "Instances", buttons[i])
inst.width = bwidth
inst.height = bheight
}

Меняя значения bwidth и bheight вы сможете сами настроить нужные размеры кнопок.

Обратите внимание, что создавая инстанс мы можем передать struct - то есть структуру данных.
Тогда не нужно будет обращаться к инстансу через переменную, но придется удалить код

width = 0;
height = 0;
При создании наших объектов, а сам код для создания инстанса преобразится следующим образом:

for (var i = 0; i < array_length(buttons); ++i)
{
instance_create_layer(room_width / 2, room_height / 2 - 50 + 100 * i, "Instances", buttons[i], {width : bwidth, height : bheight})
}
Какой из вариантов удобнее - решать вам.
Вариант с переменными, которые объявляются при создании объекта, я лично считаю более надёжным, а функциональных отличий между данными командами не так много. С другой стороны, такая возможность появилось недавно и её нужно тестировать.


Шаг шестой.

Теперь задача - сделать так, чтобы мы могли считывать, наведены ли мы сейчас на кнопку.

Для этого мы берём координаты x и y, после чего проверяем, находится ли наша мышь в области:

x - width / 2, y - height / 2, x + width / 2, y + height / 2.

Остальное - копируем из прошлого кода. Получается следующий блок:

if point_in_rectangle(dmxg, dmyg, x - width / 2, y - height / 2, x + width / 2, y + height / 2)
{
draw_set_color(c_white)
draw_set_alpha(0.15)
draw_rectangle( x - width / 2, y - height / 2, x + width / 2, y + height / 2, false)
draw_set_alpha(1)
}


Шаг седьмой.

Проделать тоже самое в событии Step. (По сути, просто заменяем instance_position)

if point_in_rectangle(dmxg, dmyg, x - width / 2, y - height / 2, x + width / 2, y + height / 2)
and mouse_check_button_pressed(mb_left)
{
//Тут код нужной кнопки
}


Шаг восьмой.

Донастраиваем все кнопки.

Какой из вариантов использовать - решать Вам.

Можно вообще использовать следующий вариант:

Создать спрайт нужных размеров и залить его белым цветом с "прозрачностью" в 1 единицу. Совершенно незаметно. Используя bbox_left / top / right / bottom нарисовать поверх прозрачной основы кнопку и проверять уже не через "point_in_rectangle", а как в первом способе.

На этом сегодняшний гайд подходит к концу.
Вкратце мы разобрали события отрисовки; как с ними работать; как работать со скриптами; как работать со шрифтами; а также вы можете смело скопировать себе и использовать несколько других скриптов в своих проектах.

Что нужно подготовить к следующему гайду:
- Минимум два спрайта "породы" - на фон (темнее) и для объекта (светлее). Размер одного спрайта - 32х32.
- Желательно спрайты нескольких объектов, вроде стен, дверей. Исходите из того, что размер одной клетки будет равен 32х32 пикселей.
- Спрайт для неба/космоса/прочего на фон на ваше усмотрение.

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

И небольшой спойлер на будущее.
Взаимодействовать с миром можно будет двумя способами: через ЛКМ и наведением "тела" игрока на тот или иной объект.

Загрузить файл проекта и всё пощупать самому можно по ссылке:
Яндекс диск

Оставшиеся темы:

- Камера и её настройка. Разные способы реализации: от простого к сложному.

- Иерархия объектов. «Объекты-родители» и их «дети». Решение часто встречающихся проблем и немного про то, как удобно выстраивать взаимодействие с объектами. Глобальные переменные.

- Массивы и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке. Включая объяснение, в каких случаях лучше использовать встроенные функции, в каких – писать свои с нуля.

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

- Иные способы хранения информации в GMS2, когда их стоит или не стоит использовать.

- Сохранение. Встроенное VS самописное.

- Звуки.

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

Лига Разработчиков Видеоигр

6.7K постов22.2K подписчика

Добавить пост

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"