D:\sideБлогС чем мы расстались в GameMaker Studio

Поднимается много вопросов о том, как портировать код с GameMaker на GameMaker Studio. Зададимся более глубоким вопросом — а почему это вообще приходится делать? Я имею в виду то, что все удалённые в GMS функции имели свои причины умереть. Некоторые из них действительно жалко, и часть их них может вернуться в ином обличии. И можно надеяться, что это произойдёт скоро… но вряд ли это будут функции, о которых я расскажу сейчас. Потому что они действительно не нужны.

Начнём, пожалуй.

execute_...(code)

Что это: Самое популярное средство для поддержки моддинга, игровой консоли и массы прочего. Функция, исполняющая текстовый фрагмент code, если это текст. Если он содержит return, то возвращённое значение будет переброшено в исполняющий код. Как обычный скрипт, по сути дела. А ещё это пара функций для запуска других программ из окружения.

Почему: По нескольким причинам. Первая — это позволило убрать из собранной игры интерпретатор GML, и тем самым немножко облегчить игру по занимаемой памяти. Второе, следствие первого — весь код транслируется ещё на этапе сборки, что исключает необходимость его хранить в игре. Что также действует на «похудение» игры. Но тут есть ещё один неочевидный момент: отсутствие вашего кода в прямом, текстовом виде затрудняет разбор логики вашей игры сильно интересующимися. Они не смогут просто найти исходный код в готовой игре и прочитать его, что в GM было возможно — им придётся идти на более сложные и тяжёлые методы.

Что более интересно, это делает значительно сложнее внедрение в игру произвольного кода, текстовый GML теперь абсолютно бесполезен и требует трансляции перед внедрением. Хотя скажу честно, я не знаю ни одного человека, который этим бы занимался, потому что для способа читерить это способ слишком изощрённый. Если он стоит применения в вашей игре, если ваша игра ворочает такими суровыми ценностями, задумайтесь — вы не зря GMS выбрали?

А что касается программ из окружения — нужно быть просто готовым к тому, что их нет и быть не может. Скажем, откуда им взяться на платформе HTML5? Или Windows Phone, под капотом которого вообще непонятно что?

Чем заменить: Самая разумная мысль, если вам что-то такое надо, это DSL. Придумайте язык, напишите машину, его разбирающую. Это не самая простая задача, но GML как языку она по силам, поэтому остаётесь только вы. Как видите, способу решения посвящена целая страница в Википедии, так что это велосипед. А значит, нужно поставить под сомнение необходимость его существования.

variable_...

Что это: Целый блок самых разных функций, связанный с переменными. А именно, работой с ними при наличии их текстового названия. Скажем, для переменной money у вас есть строчка "money", но что вы будете с ней делать? Вы обратитесь к одной из этих функций и прочитаете/запишете локальную/глобальную переменную с указанным именем. Она бывает нужна, если вы хотите инициализировать переменную, если вдруг её ещё нет, в неё ничего не записано.

Почему: Не нужны. За этой возможностью тянется целый хвост из необходимости определять существование переменной по её имени, прежде чем работать с ней. Избавиться от этого очень просто: вырезать из собранной игры все упоминания о названиях переменных, заменив их прямёхонько адресами в памяти. Хорошо бы, да? Получили бы скорость, все дела. Но в целях удобства отладки часть функциональности в этом направлении осталась, она просто недоступна к применению. Довольно странный выход из положения.

Чем заменить: Зависит от ситуации. Если вы получаете доступ к переменной по строчке, которую передаёте из другой переменной, вам поможет ds_map, и в некоторых случаях даже простейший массив — замените слова-ключи на числа-ключи и победа за вами. Если вам нужно проверять только существование — это вам не нужно. Просто всегда инициализируйте переменные чем-то содержательным и не ломайте голову над тем, что если переменную заполнять оказалось вдруг нечем, потому что такую ситуацию вы можете опознать характерным значением. Очень длинная фраза… Скажем, вы загружаете новый спрайт. У индексов спрайтов есть особенность - они целые и неотрицательные. Поэтому задав для соответствующей переменной -1 вы как бы скажете сами себе «это бред, туда ничего не написали».

Attractor, deflector, destroyer

Три вида «влияющих зон» в системах частиц GameMaker. Тут можно сказать кратко, ими просто мало кто пользовался, но для своей мощи они существенно увеличивали нагрузку от частиц на процессор. Заменить их можно, просто написав систему частиц самостоятельно на массивах. Тут вы можете подумать, что «как же, если индекс массива будет постоянно расти с новыми частицами, нам понадобится бесконечный массив». Неа. Он может не расти, если ограничить его размер максимальным значением и использовать память массива по кругу.

Есть интересная реализация структуры данных «очередь» при помощи массива: новые значения пишутся в конец, извлечение идёт с начала. Как только мы сколько-то поизвлекали, а вставки новых элементов дошли до конца массива, начинаем вставлять их на место начала, откуда элементы уже извлекли. Тонкий момент - понять, что очередь уже полная и не давать вставлять новые элементы. Таким приёмом можно реализовать систему частиц ограниченной ёмкости. Да, она будет быстрой. Возможно, настолько же быстрой, как и встроенная система частиц, особенно после компиляции с YYC. Но вам это вряд ли понадобится.

mplay_...

Буду краток: это кошмарище, использующее настолько старый DirectX API, что оно недоступно в Windows 7. Уже давно с успехом заменялось 39DLL, но не так давно (год назад?) появилась альтернатива в самой GMS: функции network_.... В сущности, они делают то же самое. И для них реализованы буферы, точно как в самой 39DLL. Так что если вам нужен мультиплеер, вы ничего не потеряли, даже наоборот: network_... умеет в такие крутые вещи, как UDP-вещание — отправка некоторого сообщения всему ближайшему сетевому окружению. Это полезно для обнаружения серверов в локальной сети.

Работа с файловой системой

Это может разочаровывать, но у GMS теперь для файлов игры личная папочка, за пределы которой ей вылезать не положено. Это сделано в угоду переносимости — некоторые ОС ограничивают приложение в правах на вылезание наружу, и правильно делают: играм нет резона иметь доступ ко всей файловой системе. А если вы делаете на GMS не игру — извините, я не привык забивать микроскопом гвозди, и вам так делать не советую. Но если вам очень нужен доступ ко всем уголкам файловой системы, напишите расширение. Только будьте готовы, что вас не все платформы пустят, куда вы хотите.

Прочее

Большинство функций вообще было удалёно либо из-за излишней Windows-специфичности (реестр?) или ПК-специфичности (CD-привод? Хотя это так старомодно), но немало функций пострадало с целью облегчить обычный цикл исполнения игры, сделав его быстрее. Лишняя скорость в игре не идёт во вред, а также работает на репутацию конструктора — «смотрите, он даже не так сильно тормозит, а местами летает», какой разрыв шаблона. С вещами из списка выше типично можно смириться или даже написать собственный их обход. Но наличие некоторых из них в коде, который вы портируете, повод задуматься над тем, о чём думал его автор. Бывает, такие вещи попадаются в скриптах расширений — это самый проблемный случай, требующий переписать проблемный код самостоятельно. Это не всегда просто, начиная с его откапывания в дебрях файла расширений. Но выполнимо.

Но несмотря на все эти «недостающие части» написать хорошую игру в GMS так же легко. Так что… это… «Го делать игры. Я создал».