D:\sideБлогHaxeFlixel после GameMaker

Каково, просидев долгие годы на очень удобном конструкторе, сделав на нём несколько игрушек, взять «сырой игровой движок» и начать шаманить с ним? Ну… это не катастрофа. Жить можно. Это многому учит из того, что конструктор делал за вас, и какую вы можете извлечь выгоду из явного управления этим делом. Я считал когда-то, что понимаю, как устроен GM. Что при большом желании, необходимости и наличии ресурсов я смогу его написать сам. И, наверное, я был прав, но я всё ещё узнал бы немало.

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

Для начала отмечу, что программы на Нaxe изначально можно было нормально собирать только в *.swf, флэш-приложения. Поэтому портировать на Haxe, преемника ActionScript (хочет того Adobe или нет), начали портировать то, что было в первую очередь полезно именно разработчикам-флэшерам. И одним из таких крайне полезных продуктов был Flixel — который называют игровым движком… с хорошей долей точности, да. В сущности — это всего лишь алгоритм управления неким списком рисуемых объектов (DisplayList). Но если разобрать любую игру на мельчайшие детали, на дне вы обнаружите что-то похожее. Опустим детали. Они здесь не важны.

Итак, появился HaxeFlixel. Но и Haxe не стоял на месте. Это вообще интересный язык, который не имеет собственного компилятора, т. е. в запускаемый машинный код напрямую не переводится. То, что называется компилятором Haxe, является на деле транслятором, переводящим исходный код на Haxe в исходный код на другом языке. И таких «других языков» сейчас очень много: C#, Java, JavaScript, C++, PHP… Но нас интересует С++.

Немножко о С++

Компиляторы для C++, я вам скажу, продвинутые. Они оптимизируют всё, что только могут, хвастаются килотонной настроек для оптимизаций, а кривой код компилируют таким образом, что он начинает работать… криво. Хотите пример? Смотрите:

#include <iostream>

int main() {
  for (int i = 0; i < 4; ++i)
    std::cout << i*1000000000 << std::endl;
}

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

#include <iostream>

int main() {
  for (int i = 0; i < 4000000000; i+= 1000000000)
    std::cout << i << std::endl;
}

И возникнет занимательная деталь. В 32-битное знаковое целое число не влезает 4 миллиарда. Только 2 с лишним. Компилятор попытается соорудить прыжок с условием, но не сможет сформулировать условие, поскольку число в указанном типе непредставимо. И цикл окажется без условия, то есть, бесконечным. Весело, да? Никаких ошибок не будет (может всплыть предупреждение), компиляция успешно завершится.

Это пример undefined behavior. Программа пришла в ту часть стандарта, в которой тот отказывается от ответственности и заявляет, что программа может вести себя как угодно — нельзя заранее предсказать, как. Ошибка есть даже в непреобразованной части, одно из выводимых в cout (оператором <<) значений не умещается тот тип, в котором представлено i, поэтому при сложении произойдёт «переполнение» (попытка записать значение больше максимального), и результат станет… отрицательным? O_o Да. «С другой стороны» диапазона значений этого типа такие же отрицательные числа. int может быть опасным, ха.

Это так, лирическое отступление. С++, кстати, стоит изучать хотя бы затем, чтобы понять, как компьютер вас понимает. Ещё лучше бы изучать С… но это уже на ваш выбор.

Итак, Haxe начал поддерживать С++…

…и это позволило Haxe вырваться за пределы флэша и с помощью разных библиотечек собирать автономные приложения, в частности — игры. Скачал, запустил, работает. Люди разогнались и собрали инструменты для сборки игр на Haxe под Windows, OSX, Linux, Android, iOS… А всё потому, что С++ на этих системах работает. HaxeFlixel не единственный инструмент на Haxe для сборки игр. Но мне он показался наиболее просто устроенным. Хотя и в нём есть свои заморочки.

Простота архитектуры

На HaxeFlixel не слишком легко разрабатывать, если раньше ничем подобным не занимались. Просто немножко удивляет, насколько всё изнутри просто устроено. Из этого, конечно, следует очевидный минус — многое нужно писать самостоятельно.

Тут спасает ассортимент объектов, доступных в самом движке. В GM выбирать не приходится — шаблон под объект всего один, предполагается его «физическое существование», наличие у него спрайта, возможноксть включения физики… У него можно включать и выключать разные вещи, из-за чего интерфейс выглядит довольно громоздко, а новички большинством этого великолепия всё равно не пользуются. Впрочем, без надобности и не трогают. Видя, что интерфейс становится сложноватым, Марк Овермарс (а тогда разработка велась под его началом) ввёл «упрощённый режим» и «расширенный режим». В упрощённом некоторые элементы управления (ненужные новичкам) прятались, и всё выглядело более-менее понятно.

В HaxeFlixel объекты выстроены в иерархию. Как, впрочем, и все типы Haxe, но нас интересуют представленные в движке.

Это, конечно, не все. Вообще можно (и нужно) создавать для своих объектов собственные классы. Но во многих случаях бывает достаточно создать один из вышеуказанных и просто задать параметры. В GM именно это и происходит, только прототип всего один и параметров очень много. Но здесь код движка компилируется вместе с вашим, на том же языке, по тем же правилам.

Заметили, что возникла цепочка из наследования? В списке каждый следующий — наследник предыдыдущего. Это не случайно, и это всего лишь одна из веток всего дерева объектов. В HaxeFlixel конструирование нового объекта обычно означает наследование от существующего. Есть ли другие подходы? Ну а то.

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

Итого два подхода, «наследовательный» (ох, какое страшное слово) и «компонентный». Возможно, есть и другие, но эти наиболее популярны и (важно!) не являются взаимоисключающими. Не могу сказать за Unity3D, но в HaxeFlixel реализовать систему компонентов не мешает решительно ничего, и это уже пытаются сделать (впрочем, пока предлагают добавить только в пакет flixel-addons, в дополнения). Кстати, компонентная система устроена внутри сложнее, и ресурсов потребует больше. Насколько? Трудно сказать. Однозначно уйдёт несколько больше оперативной памяти на хранение списка компонентов в каждом объекте; зато гораздо проще «играться» — добавлять и удалять компоненты прямо после запуска, следить за реакцией. То есть, да, ресурсы тратятся вовсе не впустую.

Аналогия в ресурсах

Ресурсы во многом совпадают с теми, что мы знаем по GameMaker. Есть растровые шрифты, графика (не разделяемая на фоны и спрайты), звуки. Объекты, по понятным причинам, попадают либо в классы, либо… так, тут сложнее, придётся объяснить.

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

Но стоп. Что же тогда такое в HaxeFlixel комната? Ответ может удивить: просто группа объектов. Вот так. Игровое пространство рассматривается движком, как общедоступное. Происходящее на условной «сцене» определяется тем, что за «актёры» на ней играют. Смена группы означает смену комнаты. Задумайтесь. GameMaker делает то же самое: он стирает из пространства все объекты старой комнаты (кроме постоянных), задаёт настройки новой комнаты (размеры окошка, проекция камеры, фоны, все дела) и создаёт описанный в комнате набор объектов на соответствующих местах.

Прикольности

Есть несколько отдельных вещей, которые мне просто понравились.

Почему стоит переходить с GMS на него?

  1. Он бесплатен. Совсем. Но требует от вас некоторых навыков и готовности много читать и тупить.
  2. Кроссплатформенность у него не особо уступает GameMaker Studio, а местами даже превосходит.
  3. Он очень просто устроен внутри. А изучая, как он устроен, можно понять, как работает GM. Вы можете продолжать им пользоваться, почему нет. Просто новополученные знания могут дать знать, как им пользоваться эффективнее и проще.
  4. Он основан на мощном языке с хорошей стандартной библиотекой. Комментарии излишни, я думаю.
  5. Настройка сборки на большей части этапов автоматизирована. Хотите собирать под Андроид? lime setup android и следуйте инструкциям. Иногда возникают косяки вроде необходимости указать, где Java, но они решаемы.
  6. На мобильные платформы игры попадают в виде скомпилированного оптимизирующими компиляторами кода на С++. Если вам нужна скорость, вы вряд ли найдёте более подходящий набор технологий.

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

Ссылочки, впоследствии коллекцию пополню:

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