Phaser - полезные советы

Часть 24: Как реализовать overflow:hidden в Phaser

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

Но у такой маски есть один недостаток, она должна быть типа Phaser.Graphics. Для быстродействия операции, можно использовать только примитивные геометрические фигуры без градиентной заливки. После такой объект можно применить к группе или спраиту через свойство mask:

mask = game.add.graphics(0, 0);
mask.beginFill(0xffffff);
mask.drawCircle(50, 50, 100);
group.mask = mask;

Но есть в Phaser возможность использовать и alphaMask. Но делается это гораздо сложней. Надо создать bitmapData объект и отрисовать в нем нужное нам изображение применяя alpha mask-у (в данном примере image и mask это ключи графических изображений, загруженных методом game.load.image())

var bitmap = game.make.bitmapData(200, 100);
bitmap.alphaMask('image', 'mask');

Дальше bitmap объект можно использовать как обычное изображение из кэша. Как вы понимаете, использовать такой механизм для составных элементов интерфейса не получиться. Если только ваш сложный элемент интерфейса не собирается в один спраит программно. Я лично пока не пробовал такой метод создания компонентов интерфейса.

Для свой программы задачу я решил очень просто. Создал изображение размером с экран игры. Центр сделал прозрачным, а к краям градиентовой маской залил белый цвет (цвет фона игры). После чего наложил это изображение поверх моих кнопок =) вот вам и alpha маска без лишнего кода и головной боли.

Если у вас есть другие решения реализации alpha маски, пожалуйста поделитесь, спасибо!

5 thoughts on “Часть 24: Как реализовать overflow:hidden в Phaser

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

  2. Я вчера собрал игру на Android-е. Работает на ура НО как и ожидал, подторжмаживает загрузка сцены выбора урока. Надо будет написать про это пост… сейчас провожу ряд тестов и пытаюсь выявить, что больше всего тормозит. К примеру нельзя использовать фильтры и изменение цвета иконок программно. Это конечно круто, но я из за этого время загрузки увеличивается на 80%. Лучше один раз перегнать все в Photoshop-е. Еще было бы хорошо как то сохранять сцены, что бы их не генерировать при каждом старте… пробовал задать параметр clearworld = false при старте сцены но не помогло (буду искать). Но вот что правда ни как не влияет на продуктивность так это полу прозрачные спрайты. Я боялся что вот такой полу прозрачный png будет тормозить… а нет, ни как не тормозит НО вот количество элементов которые анимируются (даже невидимые) очень влияют на скорость. Надо придумать как не перемещать те что за кадром, пока сам скролинг не закончился и только по завершению обновлять их. Идей очень много, вот весь день этим занимаюсь (еще повезло что смог поправить grunt что бы обновление автоматом заливалось на мобилу и уходит только 30сек на ожидание).

    п.с. про тормоза можешь не волноваться, это я спецом на самом простеньком Samsung-е тестирую, что бы если уж и тут будет работать, то на нормальном смартфоне будет летать =)

  3. у тебя сложный, но красивый интерфейс
    и это ценный эксперимент

    я когда работал в компании джуниором-программистом меня бросили на реализацию одного такого интерфейса на нативном стеке Андроид (Java). Что я скажу — анимации ресурсоемки и опасны даже на нативке. Опасны — в смысле, что легко получить всякие избыточные затраты по памяти и процессору.

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

    Хотя это тоже достаточно геморройно. Смотри сам. Иногда проще врубить режим китайского кода (это когда идет явное дублирование или повторение рутинных операций), чем писать функцию, которая его заменит.

  4. Zaxx, спасибо за откровенный отзыв. Сложный в плане понимания или технической реализации? Если второе то я вчера весь день размышляя пришел к еще одному интересному наблюдению. Мобильные игры имеют очень ограниченные ресурсы процессора. По этому, генерировать надо по мере необходимости. Приведу конкретные числа: изначально на генерацию картой выбора уроков уходило в среднем 5 секунд. Одну секунду можно сэкономить за счет замены иконок обрисованных заранее в фотошопе (от этого размер графики увеличится не более чем на 100кб, так что не слишком большая экономия от накладывания изображений, программно я делал больше для улучшения своих навыков).

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

    Наконец 2-3 секунды уходит на генерацию списка уроков — Zaxx, тут тоже есть решение… я вчера провел ряд экспериментов. Нет возможности в Phaser запускать задачу параллельно (если она использует процессорное время). Но есть обход… можно разбить работу куски и выполнять их постепенно, по очереди. Но между этими выполнениями надо делать 10мсек паузы. Я даже подумал создать этакий стэк, но пока я размышлял как это реализовать сообразил, что можно подойти к реализации этой сцены по другому. У меня в цикле генерация 16 уровней, а значит уроки каждого уровня надо генерировать с задержкой в 100мсек (через setTimeout()). Это даст возможность интерфейсу обновится, а на всю генерацию уйдет 1.5сек. Но ведь игрок уже успеет увидеть первые 2-4 уровня (а это 10-20 уроков), а пока он будет скролить, догенерируются остальные.

    На счет прокрутки — что бы ее ускорить, я попробую склеить иконку с фоном. Таким образом при перемещении надо обновлять не 62х2 объекта (иконка + фон), а всего 64 (в два раза быстрей). Ну и продолжаю думать, как сделать красиво код, который не будет перемещать невидимые элементы (для этого надо определить какие объекты могут попасть в видимый диапазон по окончанию этого swap жеста).

    п.с. Zaxx, с цветофильтрами еще одна проблема. Я когда собрал все на WebGL то на андроиде у меня все мерцало. Это баг в старых версиях андроида, но это не нам не оправдание… игрок будет считать что это у разработчика руки растут из… ты сам знаешь откуда =) А когда я переключил на Canvas, то фильтры перестали работать. Такой проблемы нет с накладыванием через globalCompositeOperation, но такой вариант тормозит. Если это игровая сцена то можно этим воспользоваться, так как запуск 2сек а игра 5 минут. Ты наверно согласишься что для сцены выбора урока, 2сек против 10сек которые пользователь выбирает какой урок запустить, не окупят себя.

  5. про цветофильтры и WebGL намотал на ус. Да, мерцание в старых мобильных браузерах присутствует — и пока таких устройств очень много (у меня самого два девайса). Поэтому в Phaser надо ставить Canvas режим. Я не знаю, почему они не пишут это большими буквами — может, потому, что по факту там мало кто думает о серьезной мобильной разработке. Или они упоролись по последним технологиям… ну знаешь, есть такие разработчики, их очень много в вебе сегодня, которые считают, что если в браузере у пользователя что-то глючит — это проблема браузера.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *