О чем этот пример
При разработке сложных игровых интерфейсов или многослойных объектов часто возникает необходимость группировать элементы. Phaser предоставляет для этого мощный инструмент — `Container`. Эта статья на практическом примере покажет, как работают вложенные контейнеры, как наследуются их свойства (например, видимость) и как правильно настраивать интерактивность для дочерних объектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('eye', 'assets/pics/lance-overdose-loader-eye.png');
}
create ()
{
const container1 = this.add.container(100, 100);
const container2 = this.add.container(200, 200);
const sprite = this.add.image(0, 0, 'eye').setInteractive();
container1.add(container2);
container2.add(sprite);
// container1.setVisible(false);
sprite.on('pointerover', function ()
{
console.log('over');
this.setTint(0xff0000);
});
sprite.on('pointerout', function ()
{
console.log('out');
this.clearTint();
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#010101',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое контейнер и зачем он нужен
Контейнер (Container) в Phaser — это специальный игровой объект, который может содержать в себе другие игровые объекты (спрайты, текст, другие контейнеры). Главное преимущество — возможность управлять всей группой как единым целым: перемещать, масштабировать, изменять видимость или вращение, применяя трансформации ко всем дочерним элементам сразу.
В примере создаются два контейнера и один спрайт.
const container1 = this.add.container(100, 100);
const container2 = this.add.container(200, 200);
const sprite = this.add.image(0, 0, 'eye').setInteractive();
Иерархия и вложенность
Ключевой момент примера — создание иерархической структуры. Объекты добавляются друг в друга с помощью метода .add(). Спрайт добавляется в container2, а container2, в свою очередь, добавляется в container1.
container1.add(container2);
container2.add(sprite);
Таким образом, спрайт становится «внуком» для container1. Все трансформации (позиция, видимость), примененные к родительскому контейнеру, будут каскадно применены ко всем его потомкам.
Наследование свойства видимости
В закомментированной строке кода показана одна из самых полезных особенностей контейнеров.
// container1.setVisible(false);
Если раскомментировать этот вызов, container1, а вместе с ним и все его дочерние элементы (container2 и sprite), станут невидимыми. Это происходит потому, что свойство visible родительского объекта влияет на конечную видимость всех потомков в дереве сцены. Это мощный механизм для управления целыми слоями или группами объектов одной командой.
Интерактивность внутри контейнеров
Спрайту явно задается интерактивность с помощью .setInteractive(). Это позволяет ему обрабатывать события указателя (мыши, касания).
const sprite = this.add.image(0, 0, 'eye').setInteractive();
Обратите внимание: координаты спрайта (0, 0) задаются относительно своего родителя — container2. А глобальное положение спрайта на холсте рассчитывается как сумма смещений всех его родителей: container1 (100,100) + container2 (200,200) + sprite (0,0). Интерактивность и события работают с итоговыми, мировыми координатами объекта.
Обработка событий указателя
В примере на спрайт повешены обработчики событий pointerover и pointerout.
sprite.on('pointerover', function ()
{
console.log('over');
this.setTint(0xff0000);
});
sprite.on('pointerout', function ()
{
console.log('out');
this.clearTint();
});
Когда курсор наводится на спрайт, в консоль выводится 'over', и спрайт окрашивается в красный цвет с помощью setTint(). При уходе курсора — выводится 'out', и оттенок снимается. Важно, что эти события будут срабатывать, даже если спрайт находится глубоко внутри иерархии контейнеров, при условии, что все родители видимы.
Что попробовать дальше
Вложенные контейнеры в Phaser — это фундаментальный инструмент для организации сложных игровых объектов и UI. Они позволяют применять трансформации каскадно и централизованно управлять группами. Для экспериментов попробуйте
- Раскомментировать
container1.setVisible(false)и убедиться, что интерактивность спрайта тоже пропадает - Изменить порядок добавления объектов в контейнеры
- Добавить перемещение
container1с помощьюthis.tweens.add()и наблюдать, как вся группа плавно движется как единое целое
