18

Gamemaker Studio 2. Система для создания простых модификаций

Серия Gamemaker Studio 2: Сборная солянка

Привет!

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

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

Описание системы

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

Реализация

Для удобства я сделал два объекта:
oWeaponsManager (со свойством persistent) и oWeapon.
Первый - управляющий. Он создаётся вместе с другими управляющими объектами при запуске и здесь происходит основная логика, о которой мы с вами будем сегодня говорить.
Второй объект - это объект-оружие, которому мы в последствии будем передавать всю нужную информацию, спрайты и прочее-прочее.

Ссылка на код:
https://pastebin.com/T6NaBMsb

Дубль с пастебина:
Функция-конструктор для объектов:

function scrWeaponsAdd(_sprite_index, _images, _name, _distance, _penetration, _damage) constructor{
sprite_index = _sprite_index;
images = _images;
name = _name;
distance = _distance;
penetration = _penetration;
damage = _damage;
}
oWeaponsManager:
// Если файл уже существует - заполняем по новой.
if file_exists("weapons.txt") {
global.weapons = [];
var _buffer = buffer_load("weapons.txt");
var _string = buffer_read(_buffer, buffer_string);
buffer_delete(_buffer);
var _loadData = json_parse(_string);
// Загружаем оружие.
for (var i = 0; i < array_length(_loadData); ++i) {
// Если информация является строкой или такого спрайта не существует - создаём его и сохраняем
if is_string(_loadData[i].sprite_index) or !sprite_exists(_loadData[i].sprite_index) {
var name = _loadData[i].sprite_index;
if file_exists(name) {
var sprite = sprite_add(name, _loadData[i].images, false, false, 0, 0);
// Устанавливаем точку отсчёта в центре спрайта
sprite_set_offset(sprite, sprite_get_width(sprite) / 2, sprite_get_height(sprite) / 2);
_loadData[i].sprite_index = sprite;
}
}
array_push(global.weapons, _loadData[i]);
}
}
// Создаём с нуля, если не существует
else {
global.weapons = [
new scrWeaponsAdd(sPistol, 1, "Пистолет", 10, 1, 10),
]
var _string = json_stringify(global.weapons);
var _buffer = buffer_create(string_byte_length(_string) + 1, buffer_fixed, 1);
buffer_write(_buffer, buffer_string, _string);
buffer_save(_buffer, "weapons.txt");
buffer_delete(_buffer);
}
#endregion
#region Удаляем те объекты, что не смогли загрузиться
var i = 0;
while i != array_length(global.weapons) {
if is_string(global.weapons[i].sprite_index) {
array_delete(global.weapons, i, 1);
i -= 1;
}
i += 1;
}
#endregion
#region Создаём прошедшие проверку объекты. Дебаг.
for (var i = 0; i < array_length(global.weapons); ++i) {
var inst = instance_create_layer(32 + i * 32, 32, "Instances", oWeapon);
inst.sprite_index = global.weapons[i].sprite_index;
}
#endregion

Спрайты можно загружать как анимированные, так и одиночные. Всё зависит от параметра images, который должен быть равен количеству кадров. Принимает на вход: .png, .jpeg/jgp, .json, .gif.

Теперь немного интересностей. Как видно из кода, я добавляю только одно оружие, которое у меня в проекте уже имеет свой спрайт. Как загрузить второе? Всё просто.

Сочетанием клавиш "Windows + R" (или просто открыв окно "выполнить", либо прокликав пусть самостоятельно), вписывем туда: %localappdata%
Откроется папка Диск:\Пользователи\Пользователь\AppData\Local
Здесь ищем папку, название которой совпадает с названием нашего проекта. У меня это Pikabu.

Именно в эту папку у нас сохраняются файлы, с которыми мы работали. То есть, и сохранения, и файл weapons.txt, у нас находится здесь.
Чтобы добавить новое оружие - скинем его картинку в эту папку, затем немного подредактируем файл weapons.txt

Скопируем первую часть строки, что в фигурных скобках. Добавим запятую после закрывающей фигурной и вставим скопированный текст.
Что нам нужно заменить:
images - с 1 меняем на нужное число кадров. Как видно по скрину выше, у меня это число будет равняться трём, так как я хочу импортировать "анимированную" картинку. Важно знать, что на это число будет разделена картинка по ширине. Для анимации картинка должна быть выполнена в виде линии, где меняется только ширина. Хотите спрайт 32х32 с тремя кадрами анимации - делайте картинку 96х32 и размещайте в каждой новой "клетке" то, что нужно отрисовать.
sprite_index - пишем в кавычках полное название нашего файла. Полное название - это с учётом его формата. В моём случае - "sPistol3.png"
name, distance, penetration, damage - меняем по своему усмотрению, это уже чисто игровые параметры.
Сохраняем файл и заходим в игру, чтобы посмотреть результат.

Эпилептикам советую быть осторожнее.

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

Теперь поговорим о минусах.

Первый из них - нагрузка. Для хранения каждого спрайта, загруженного "извне", движок создаёт свою текстурную карту. От этого больше нагрузка на память. Со спрайтами, которые импортированы в движок, нагрузка меньше.
Замечу, что нагрузка хоть и выше, но не существенно и эта проблема, если начнёт мешать, может быть решена как удалением ненужных спрайтов (ведь их можно спокойно подгружать и выгружать, они же хранятся у нас в папке проекта), так и иными методами.
Второй - определённые требования к структуре проекта. Как вы могли заметить, под оружие у меня всего один объект и в нём в дальнейшем будет расписана логика работы для всех доступных видов вооружения. Не всем это может быть удобно, но таков путь.

Если что-то пошло не по плану, посмотреть исходный код можно здесь:
https://disk.yandex.ru/d/bOSzQ5bj8IdN9w

P.S.
Комната была уменьшена в размерах с 1920х1080 до 128х128, чтобы показать оба объекта.
P.P.S.
Если не получается найти папку, то можете в коде oWeaponsManager, после создания файла weapons.txt, прописать следующий код:
show_debug_message(filename_path("weapons.txt"))
И запустить игру. В выводе выскочит сообщение с путём прямиком до нужной папки.

Если что-то не получилось - пишите, постараюсь помочь.

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

ЗАПРЕЩЕНО:

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

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

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


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

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

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

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

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

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества