О чем этот пример
Визуальная сложность игровых сцен часто требует тонкого контроля над порядком отрисовки объектов. Phaser 3 предоставляет мощный инструмент — `Layer` (слои), который работает как специализированный контейнер для отображения. Эта статья покажет, как создавать несколько слоев и динамически перемещать игровые объекты между ними прямо во время выполнения. Этот подход полезен для реализации механизмов перетаскивания интерфейса, изменения глубины объектов (например, когда персонаж заходит за дерево) или организации сложных сцен с независимыми группами элементов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('cake', 'assets/sprites/strawberry-cake.png');
}
create ()
{
this.add.text(10, 10, 'Click Sprite to move between Layers');
const size1 = this.add.text(10, 48);
const size2 = this.add.text(410, 48);
this.add.line(400, 300, 0, 0, 0, 600, 0xffffff);
const layer1 = this.add.layer();
const layer2 = this.add.layer();
for (let i = 0; i < 8; i++)
{
const x = Phaser.Math.Between(64, 336);
const y = Phaser.Math.Between(128, 536);
const sprite = new Phaser.GameObjects.Sprite(this, x, y, 'cake');
layer1.add(sprite);
sprite.setInteractive();
sprite.on('pointerdown', () => {
if (sprite.displayList === layer1)
{
layer2.add(sprite);
sprite.x += 400;
}
else
{
layer1.add(sprite);
sprite.x -= 400;
}
size1.setText('Layer 1 size: ' + layer1.length);
size2.setText('Layer 2 size: ' + layer2.length);
});
}
size1.setText('Layer 1 size: ' + layer1.length);
size2.setText('Layer 2 size: ' + layer2.length);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание слоев и их роль
В Phaser 3 Layer — это особый тип игрового объекта, наследующий от GameObject. Его ключевая задача — управлять списком отображения (Display List) для группы дочерних объектов. В отличие от простого добавления спрайтов напрямую в сцену, использование слоев дает вам изолированный контекст для управления их порядком и свойствами.
В примере создаются два независимых слоя, которые будут содержать спрайты торта. Разделительная линия на экране визуально разграничивает их области влияния.
const layer1 = this.add.layer();
const layer2 = this.add.layer();
Динамическое добавление объектов и обработка событий
Объекты не добавляются в сцену напрямую. Вместо этого они создаются через конструктор Phaser.GameObjects.Sprite и затем помещаются в слой с помощью метода layer.add(). Каждому спрайту назначается интерактивность через setInteractive(), что позволяет обрабатывать клики.
Обратите внимание, что каждый спрайт получает обработчик события pointerdown. Именно внутри этого обработчика и происходит магия перемещения между слоями.
const sprite = new Phaser.GameObjects.Sprite(this, x, y, 'cake');
layer1.add(sprite);
sprite.setInteractive();
sprite.on('pointerdown', () => {
// Логика перемещения будет здесь
});
Логика перемещения и свойство displayList
Сердце примера — проверка текущего слоя объекта через свойство displayList. Это свойство ссылается на контейнер (слой или саму сцену), в котором в данный момент находится объект.
Если sprite.displayList равен layer1, объект перемещается в layer2 и его координата X увеличивается на 400 пикселей, что визуально сдвигает его в правую часть экрана. Если объект уже в layer2, он возвращается в layer1 со сдвигом влево. Важно: метод layer.add() автоматически удаляет объект из его предыдущего родительского списка отображения.
if (sprite.displayList === layer1)
{
layer2.add(sprite);
sprite.x += 400;
}
else
{
layer1.add(sprite);
sprite.x -= 400;
}
Отслеживание состояния слоев
Каждый слой имеет свойство length, которое показывает количество содержащихся в нем игровых объектов. В примере это свойство используется для обновления текстовых полей, отображающих текущий размер каждого слоя. Это наглядно демонстрирует, как объекты физически покидают один список и добавляются в другой.
size1.setText('Layer 1 size: ' + layer1.length);
size2.setText('Layer 2 size: ' + layer2.length);
Что попробовать дальше
Использование Layer предоставляет чистый и производительный способ управления группами объектов. Вы можете применять трансформации, эффекты или изменять видимость сразу для всего слоя. Для экспериментов попробуйте
- Добавить разные типы объектов (текст, графику) в один слой
- Реализовать систему «поднятия» объекта на верхний слой при клике
- Управлять глубиной (
depth) объектов внутри одного слоя для тонкой настройки порядка отрисовки внутри группы
