Defold. Некоторые сложности и их решения.

2016-06-27_23-19-45Читая предыдущий пост о Defold может сложится впечатление, что движок идеален и просто «серебряная пуля». Да, так и есть ^___^.  В этот раз я расскажу о сложностях, с которыми  столкнулся и как они решаются.

render_script

— это lua скрипт, в котором весь render pipeline, как на ладони. Там можно менять размер и пропорции видимой области,  порядок отрисовки, проекцию камеры и многое другое. Подробности о том, что же умеет render_script и как подменить встроенный скрипт своим, можно прочитать в официальной документации, а здесь про конкретные задачи и их решения.

Game Scale

Скейл игры под разные разрешения чуть ли не самая первая и основная задача. В нашей игре необходимо вписать игровую область в экран по одной из сторон, сохраняя пропорции, и затем центрировать. В примерах на github есть готовое решение скейла по таким правилам. Единственное отличие в моей версии в том, что уровни у меня разные по размеру. Поэтому в разрешение экрана я вписываю не фиксированный размер игры, а текущий размер уровня, который передаю сообщением в render_script при старте уровня. Выглядит это так:

Render predicates

— определяет порядок отрисовки по тэгу в материале. Подробности со всеми премудростями в документации, а вот где это пригодилось  в проекте.

GUI в движке Defold независимая сущность со своими типами объектов, в которую нельзя поместить все, что вздумается. Мне же вздумалось использовать партиклы в GUI. Вроде, все просто. Вешаем компонент фабрики на тот же объект, что и компонент GUI и при создании нового партикла задаем нужные координаты. У меня это место появления звезды. Но, вот беда, наши частицы отрисовываются под звездой и z на это никак не влияет. Можно, конечно, начать убиваться и материться мол «Как же так, партиклы обычная вещь для ГУИ, что за фигня … «, но вместо этого идем на форум и в документацию и находим решение.

2016-06-27_21-21-58Для начала создадим копию материала, что используется для партиклов. По умолчанию он находится в builtins/materials/ particlefx.material . Зададим ему tag, у меня это gui_particle. Далее идем в наш render_script и создадим там новый предикат. А после отрисуем его там, где положено. Выглядит это примерно вот так:

Теперь у нас есть материал, который мы можем задавать для всех партиклов, которые нужно отрисовать над GUI.

Materials

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

Над текущим проектом, мне повезло работать с замечательным человеком, который очень внимательно относится к деталям. Именно он и оторвал меня от «угара» написания игровой логики и, уже на ранних прототипах, предложил решить следующую проблему:
ful
Как видно, левая картинка намного четче, чем правая (несмотря на то, что изображение уже пережато несколько раз). Так вот, левый скриншот сделан при скейле 1, а правый при скейле 0.5. В принципе, при любом скейле отличным от 1 картинка заметно «плывет». Из опыта работы на флэш родилась мысль об использовании нескольких наборов текстур, и все знакомые flash разработчики пропагандировали именно этот подход. Но опыт работы с unity подсказывал, что копать нужно в сторону сжатия текстур. После тщательного изучения форума и документации  таки решил спросить сообщество как с этим быть, ответили мне моменталтно и решение оказалось крайне простым.

2016-06-27_22-12-12В настройках материала мы можем создать sampler и задать его тип фильтрации. В моем случае, необходимо было задать FILTER_MODE_LINEAR. Но здесь есть один нюанс, который я упустил. Сэмплер — это тип переменной шейдера. Создавая его в материале, мы просто добавляем параметры для переменной, которую укажем в поле name. А переменная эта задается в шейдере. Например, этот скриншот для материала sprite использует шейдер sprite.fp :

Именно DIFFUSE_TEXTURE мы и должны указать в качестве значения поля name в samplers. А вот шейдер gui.fp используемый в материале gui:

Здесь переменная сэмплер имеет имя texture, поэтому, не забываем смотреть на код шейдера и в параметрах материала писать правильное имя переменной сэмплера.

Теперь у нас четкая картинка с любым скейлом 🙂

result

Другое.

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

Конечно, есть еще всякие мелочи:

  • встроенный твинер не умеет работать с пользовательскими векторами (но умеет с некоторыми свойствами объектов, что являются векторами) — уже создана таска. Штука совершенно не критичная и легко обходится.
  • нет события на окончание партикла. Тоже очень минорная задача, которая обходится маленьким скриптом. Но и этот вопрос поднимался на форуме и таск уже создан.
  • невозможно просто взять и ускорить спрайтовую анимацию, об этом уже писал у себя в блоге Андрей Лапшин. Таска тоже создана и на форуме есть код, как это обойти. Да, велосипед, но не смертельно.

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

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