О чем этот пример
Контейнеры в Phaser — мощный инструмент для группировки игровых объектов. Но их иерархическая природа имеет нюансы, особенно при управлении видимостью. Эта статья разбирает, как свойство `visible` распространяется по цепочке родительских и дочерних контейнеров. Понимание этого механизма критически важно для создания сложных интерфейсов, многосоставных персонажей или уровней, где нужно скрывать целые группы объектов одним вызовом.
Версия 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');
container1.add(container2);
container2.add(sprite);
this.input.once('pointerdown', () =>
{
container2.setVisible(false);
console.log('off', container2.visible);
});
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#010101',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Суть примера: иерархия контейнеров
Пример создаёт простую цепочку из двух контейнеров и одного спрайта. Контейнеры в Phaser (Phaser.GameObjects.Container) могут содержать любые другие игровые объекты, включая другие контейнеры, образуя древовидную структуру.
const container1 = this.add.container(100, 100);
const container2 = this.add.container(200, 200);
const sprite = this.add.image(0, 0, 'eye');
container1.add(container2);
container2.add(sprite);
В этом коде container1 является корневым контейнером. В него добавлен container2 как дочерний объект. В container2, в свою очередь, добавлен спрайт sprite. Таким образом, спрайт является «внуком» для container1.
Как работает свойство `visible`
Свойство visible определяет, будет ли объект отрисован на экране. Особенность контейнеров в том, что они управляют видимостью всего своего поддерева. Если контейнер невидим, все его дочерние объекты также не будут отображены, независимо от их собственного значения visible.
В примере обработчик клика меняет видимость среднего звена в цепочке:
this.input.once('pointerdown', () => {
container2.setVisible(false);
console.log('off', container2.visible);
});
После вызова container2.setVisible(false) сам container2 и любой его потомок (в нашем случае — спрайт) перестают отрисовываться. При этом container1 остаётся видимым, но так как его единственный видимый потомок (container2) теперь скрыт, на экране не будет отображено ничего.
Проверка видимости на практике
Важно понимать разницу между фактической видимостью объекта на экране и значением его свойства visible. Свойство object.visible может быть true, но если любой из его родителей в иерархии контейнеров невидим, объект всё равно не будет показан.
// После скрытия container2:
console.log(sprite.visible); // Вернёт true!
Несмотря на то что спрайт физически не виден на холсте, его свойство sprite.visible останется равным true. Это логично, так как спрайт сам по себе не менял своего состояния — его скрыл родитель. Для проверки, виден ли объект в данный момент в рамках всей сцены, нужно анализировать всю цепочку родителей.
Когда это полезно?
Такое поведение — не баг, а фича, которая открывает удобные возможности для управления игрой.
* **Слои интерфейса:** Вы можете собрать все элементы меню паузы в один контейнер и скрывать/показывать всю панель одной командой container.setVisible().
* **Сложные объекты:** Персонажа, состоящего из тела, оружия и эффектов, можно собрать в контейнер. Его временное исчезновение (например, при использовании навыка невидимости) реализуется в одну строку.
* **Управление уровнями:** Группировка всех объектов определённой локации или «комнаты» в контейнер позволяет быстро выгружать и загружать контент, упрощая организацию кода.
Использование контейнеров для таких задач эффективнее, чем ручное переключение видимости каждого объекта в массиве.
Что попробовать дальше
Иерархия контейнеров в Phaser обеспечивает мощный и логичный контроль над группами объектов через наследование видимости. Запомните: если родительский контейнер скрыт, все его потомки не отрисуются, даже если их локальное свойство visible равно true. Для экспериментов попробуйте
- добавить в
container1ещё один спрайт напрямую и убедиться, что он остаётся видимым после скрытияcontainer2 - создать более глубокую вложенность контейнеров (3-4 уровня) и поуправлять видимостью на разных этажах этой иерархии
