HTML5 Phaser ECMAScript 6

Часть 15: Используем карту Tilemap для интерфейса (шаг 1)

Начну пост с позитивной ноты — мне удалось создать интерфейс сцены с помощью Tiled редактора. Кому нетерпится посмотреть на результат, последний вариант игры тут.

вот как выглядит игра на данный момент (к сожалению gif вышел большим, по этому анимацию смотрите по ссылке выше)

Сложность не заключалась в использовании tilemap для генерации интерфейса. Надо было все сделать так, что бы визуальное редактирование сцены не требовало изменений самого кода. Получилось сделать это не сразу, от части из за того, что Phaser не полностью реализовал все возможности tilemap, и от части из за нехватки опыта. Генерацию спраитов мы делаем методом createFromObjects():

tile_map.createFromObjects('misc', 10, 'map_icon_arrow', 0, true, false, this.misc);

Первый параметр это имя слоя (задается в Tiled редакторе). Дальше идет идентификатор спраита объекты которого надо создать (это число можно найти в xml файле карты). Третьим параметром передаем уникальный ключ спраита и порядковый номер кадра, если мы использовали spritesheet вместо image. Обратите внимание, последний параметр это группа, в которую будет добавлен созданный объект. Но меня больше интересовало, использование метода createFromObjects() для создания спраитов на базе своего Sprite класса:

this.stage_map.createFromObjects('menu', 1, null, null, true, false, this.menu, ScoreBar);

ScoreBar это составной компонент, который состоит из фона, числового значения и анимированной иконки. Не все так просто… Во первых: у нас нет возможности передать дополнительные параметры (иконка и выравнивание текста) при генерации ScoreBar объекта. Во вторых: метод createFromObjects() не возвращает созданный объект.

назчание объекта и его уникальные параметры

В программе Tiled есть возможность задать имя каждому объекту. Это значит, если написать свой метод создания объекта, достаточно ему передать имя слоя, имя объекта и класс (все остальное уже прописано в файле карты). Начнем с поиска нужного объекта:

for (var i in this.stage_map.objects[layer])
  if (this.stage_map.objects[layer][i].name == name)
    var object = this.stage_map.objects[layer][i];

Тут я подумал, под полем name в Tiled программе есть еще и поле type. Почему бы не передать имя класса через него? Тогда создание объекта сводилось на:

var sprite = new window[object.type](this.game, x, y, key);

Но не тут то было… в отличии от JavaScript 5 в 6 версии, классы не прописаны в глобальной переменной window. Проблему удалось решить создав массив с именами всех классов:

const CLASSES = {ScoreBar, LevelButton};
var sprite = new CLASSES[object.type](this.game, object.x, object.y);

Заработало! Теперь надо было решить задачу передачи дополнительных параметров конструктору. Программа Tiled позволяет задать свойства для каждого объекта отдельно в редакторе. При считывании такой карты, Tilemap автоматом их добавляет к каждому найденному объекту. Получалось достаточно переместить код инициализации из constructor() в init() метод и дело в шляпе. createFromObjects() метод создавал бы только скелет, а вот метод init() превращает бы его в нужный элемент интерфейса. Но мне показалось, что более изящно было бы передать параметры непосредственно конструктору:

var args = [this.game, object.x, object.y];
for (var i in object.properties)
  args.push(object.properties[i]);
var sprite = Object.create(CLASSES[object.type].prototype);
CLASSES[object.type].apply(sprite, args);

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