О чем этот пример
В разработке игр часто возникает необходимость работать с группами объектов как с единым целым: перемещать, масштабировать или скрывать несколько элементов одновременно. Контейнеры в Phaser предоставляют мощный инструмент для организации таких групп в рамках отображаемого списка. Эта статья покажет, как динамически добавлять игровые объекты в контейнер по клику мыши, что полезно для создания интерактивных интерфейсов, инвентарей или систем частиц, где элементы появляются в ответ на действия игрока.
Версия 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 Sprite to Container').setDepth(1);
const size = this.add.text(10, 32, 'Container size: 0').setDepth(1);
const container = this.add.container();
this.input.on('pointerdown', pointer => {
const x = pointer.worldX;
const y = pointer.worldY;
const sprite = new Phaser.GameObjects.Sprite(this, x, y, 'cake');
container.add(sprite);
size.setText('Container size: ' + container.length);
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание сцены и загрузка ресурсов
Основой любого примера в Phaser является класс сцены, расширяющий Phaser.Scene. В его методе preload мы загружаем графические ресурсы, которые будут использоваться в качестве спрайтов.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('beer', 'assets/sprites/beer.png');
// ... другие изображения
}
Метод setBaseURL устанавливает базовый URL для загрузчиков, что позволяет указывать только относительные пути к файлам. Загружаемые изображения (например, 'cake') позже будут использоваться как текстуры для спрайтов.
Инициализация контейнера и текстовых полей
В методе create происходит начальная настройка игрового мира. Здесь создаются два текстовых объекта для вывода информации и, что важнее, пустой контейнер.
create ()
{
this.add.text(10, 10, 'Click to add Sprite to Container').setDepth(1);
const size = this.add.text(10, 32, 'Container size: 0').setDepth(1);
const container = this.add.container();
}
Метод this.add.container() создает новый пустой контейнер и автоматически добавляет его на сцену. Контейнер — это особый тип игрового объекта, который может содержать в себе других детей (дочерние объекты), включая другие контейнеры. Установка setDepth(1) для текста гарантирует, что он будет отображаться поверх других графических элементов.
Обработка клика и динамическое создание спрайтов
Ключевая логика примера привязана к событию клика мыши. Мы настраиваем слушатель на событие 'pointerdown'.
this.input.on('pointerdown', pointer => {
const x = pointer.worldX;
const y = pointer.worldY;
const sprite = new Phaser.GameObjects.Sprite(this, x, y, 'cake');
});
Свойства pointer.worldX и pointer.worldY содержат координаты клика в игровом мире. На их основе создается новый экземпляр спрайта Phaser.GameObjects.Sprite. Конструктор принимает ссылку на сцену (this), координаты и ключ текстуры, загруженной ранее.
Добавление спрайта в контейнер и обновление счетчика
Созданный спрайт необходимо добавить в контейнер. Это делается с помощью метода add контейнера.
container.add(sprite);
size.setText('Container size: ' + container.length);
Метод container.add(sprite) помещает спрайт в контейнер. С этого момента спрайт становится дочерним элементом контейнера. Его позиция, вращение и масштаб будут рассчитываться относительно контейнера, если у контейнера будут заданы соответствующие трансформации. Свойство container.length отражает текущее количество дочерних объектов в контейнере, и мы обновляем текстовое поле, чтобы отобразить это число.
Что попробовать дальше
Контейнеры в Phaser — это фундаментальный механизм для структурирования игровых объектов. Динамическое добавление элементов, как показано в примере, открывает путь к созданию сложных интерактивных систем. Для экспериментов попробуйте
- добавлять спрайты с разными текстурами ('beer', 'watermelon') в зависимости от позиции клика
- применить трансформации (например,
container.setRotation(0.5)) ко всему контейнеру после добавления нескольких спрайтов и наблюдать, как все дети меняются вместе - реализовать удаление спрайтов из контейнера по второму клику, используя
container.remove(sprite)и обновляя счетчик
