О чем этот пример
В Phaser игровые объекты автоматически добавляются в сцену при создании через фабричные методы типа `this.add.image()`. Но что, если нам нужно создать объект через `new` и вручную управлять его появлением? В этой статье мы разберем метод `sprite.addToDisplayList()`, который позволяет добавлять созданные вручную спрайты в систему отображения сцены. Это полезно для продвинутого управления жизненным циклом объектов, их пулинга или интеграции с кастомными системами.
Версия 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('beer', 'assets/sprites/beer.png');
this.load.image('watermelon', 'assets/sprites/watermelon.png');
this.load.image('cake', 'assets/sprites/cake.png');
}
create ()
{
this.add.text(10, 10, 'Click to add a Sprite').setDepth(1);
const size = this.add.text(10, 32, 'Display List size: 2').setDepth(1);
this.input.on('pointerdown', pointer => {
const x = pointer.worldX;
const y = pointer.worldY;
const sprite = new Phaser.GameObjects.Sprite(this, x, y, 'watermelon');
sprite.addToDisplayList();
size.setText('Display List size: ' + this.children.length);
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Стандартный и ручной способы добавления
Обычно, чтобы добавить спрайт, вы используете встроенный фабричный метод сцены. Он сразу создает объект и добавляет его в Display List.
// Стандартный способ. Объект сразу виден.
const sprite = this.add.image(100, 100, 'beer');
Однако иногда объект нужно создать через ключевое слово new. Это может понадобиться для наследования, пула объектов или сложной логики инициализации. В этом случае объект существует в памяти, но не принадлежит сцене и не отображается.
// Ручное создание. Объект НЕ добавлен в сцену и не отображается.
const sprite = new Phaser.GameObjects.Sprite(this, 100, 100, 'watermelon');
Волшебный метод addToDisplayList()
Чтобы вручную созданный спрайт стал видимым и управляемым сценой, нужно вызвать у него метод addToDisplayList(). Этот метод регистрирует объект в системах сцены: в Display List (для отрисовки) и в списке обновления.
// Создаем объект вручную
const sprite = new Phaser.GameObjects.Sprite(this, x, y, 'watermelon');
// Добавляем его в системы отображения и обновления сцены
sprite.addToDisplayList();
После вызова этого метода спрайт начинает отрисовываться и получать вызовы update (если он активен). В примере из статьи мы делаем это по клику мыши, добавляя новый спрайт в позиции курсора.
Порядок и проверка добавления
Метод addToDisplayList() можно вызывать только у объектов, которые еще не добавлены в сцену. Повторный вызов не даст эффекта. После добавления объект попадает в массив this.children, который хранит все дочерние объекты сцены.
// Обновляем текст, чтобы показать размер списка детей сцены
size.setText('Display List size: ' + this.children.length);
Этот массив автоматически обновляется при добавлении или удалении объектов. В примере мы используем его длину, чтобы наглядно демонстрировать, что каждый клик увеличивает количество объектов в сцене.
Практическое применение: пул объектов
Главная практическая польза addToDisplayList() и его парного метода removeFromDisplayList() — создание пулов (pools) объектов. Это оптимизирует производительность, позволяя переиспользовать объекты вместо их постоянного создания и удаления.
// Примерный каркас для пула
class SpritePool {
constructor(scene, texture) {
this.scene = scene;
this.texture = texture;
this.pool = []; // Массив неактивных спрайтов
}
get(x, y) {
let sprite = this.pool.pop();
if (!sprite) {
// Создаем новый объект вручную
sprite = new Phaser.GameObjects.Sprite(this.scene, x, y, this.texture);
} else {
// Переиспользуем существующий
sprite.setPosition(x, y);
sprite.setActive(true).setVisible(true);
sprite.addToDisplayList(); // Возвращаем в сцену
}
return sprite;
}
release(sprite) {
sprite.removeFromDisplayList(); // Убираем из сцены
sprite.setActive(false).setVisible(false);
this.pool.push(sprite); // Отправляем в пул
}
}
Что попробовать дальше
Метод addToDisplayList() — это ключ к низкоуровневому контролю над игровыми объектами в Phaser. Он открывает дорогу для оптимизаций через пулы объектов, сложных композиций и кастомных систем управления сценой. Для экспериментов попробуйте создать систему частиц, где каждая частица будет создаваться через new и добавляться в сцену по мере необходимости, или реализуйте сложный интерфейс с динамически собираемыми из компонентов элементами.
