О чем этот пример

Эффективная загрузка ресурсов — основа быстрой и плавной игры. В Phaser вы можете не только дожидаться полной загрузки всех файлов, но и реагировать на завершение загрузки каждого из них мгновенно. Это позволяет оптимизировать процесс: показывать прогресс, немедленно использовать загруженные текстуры для создания фона или инициализировать объекты по мере их поступления, сокращая время ожидания игрока.

Версия 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.on('filecomplete', function (key, file) {

        //     this.add.image(400, 300, key);

        // }, this);

        this.load.image('taikodrummaster', 'assets/pics/taikodrummaster.jpg').on('filecomplete', this.addImage, this);

        this.load.image('sukasuka-chtholly', 'assets/pics/sukasuka-chtholly.png');
    }

    addImage (key, file)
    {
        this.add.image(400, 300, key);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    pixelArt: true,
    scene: Example
};

const game = new Phaser.Game(config);

Суть события `filecomplete`

Менеджер загрузки Phaser (this.load) является эмиттером событий. Одно из ключевых событий — filecomplete. Оно генерируется каждый раз, когда отдельный файл (изображение, аудио, JSON и т.д.) успешно загружен и обработан.

Это событие передает в функцию-обработчик два параметра: 1. key — строковый ключ, по которому ресурс был зарегистрирован. 2. file — объект Phaser.Loader.File, содержащий детальную информацию о загруженном файле.

Использование этого события позволяет разорвать жесткую связь между моментом окончания загрузки всех ресурсов (событие complete) и моментом начала их использования.

Практический пример: Немедленный вывод изображений

Рассмотрим исходный код примера. В методе preload() мы настраиваем загрузку двух изображений. Важный момент — мы подписываемся на событие filecomplete для первого изображения, используя цепочку вызовов.

this.load.image('taikodrummaster', 'assets/pics/taikodrummaster.jpg').on('filecomplete', this.addImage, this);

Здесь метод .on() вызывается не на самом менеджере загрузки, а на объекте File, который возвращает this.load.image(...). Это регистрирует обработчик this.addImage конкретно для события завершения загрузки файла 'taikodrummaster'. Последний аргумент this задает контекст выполнения для функции обратного вызова.

addImage (key, file)
{
    this.add.image(400, 300, key);
}

Как только изображение 'taikodrummaster' загрузится, будет вызвана функция addImage. Она получает ключ ресурса и немедленно создает изображение в центре сцены, используя этот ключ через this.add.image. Второе изображение ('sukasuka-chtholly') загрузится после, но отображено не будет, так как для него обработчик не зарегистрирован.

Глобальная vs. Локальная подписка на события

В закомментированном коде примера показан альтернативный, более глобальный подход.

// this.load.on('filecomplete', function (key, file) {
//     this.add.image(400, 300, key);
// }, this);

Здесь метод .on() вызывается непосредственно на объекте this.load. Это означает, что указанная функция-обработчик будет вызвана при завершении загрузки *каждого* файла в этой сцене. Если раскомментировать этот блок и закомментировать цепочку вызовов, то оба изображения ('taikodrummaster' и 'sukasuka-chtholly') будут отображены на сцене одно поверх другого.

Выбор подхода зависит от задачи: глобальная подписка удобна для универсальных действий (например, обновления полоски прогресса), а локальная — для специфической логики, привязанной к конкретному ресурсу.

Типичные сценарии использования

1. **Динамическое создание интерфейса:** Можно начать отрисовку статического фона или элементов меню сразу после их загрузки, не дожидаясь, например, больших аудиофайлов. 2. **Кастомный индикатор прогресса:** Вместо стандартной полоски можно выводить процент загрузки для каждого типа ресурсов или менять подсказки на экране загрузки. 3. **Поэтапная инициализация игры:** Сначала загружаются и отображаются критически важные ресурсы для стартового экрана, а остальные (для 2-го уровня, дополнительные эффекты) могут подгружаться фоном позже. 4. **Обработка ошибок:** Можно отслеживать событие loaderror для каждого файла, чтобы предпринять альтернативные действия (например, загрузить ресурс с резервного сервера).

Что попробовать дальше

Событие filecomplete — это мощный инструмент для тонкого контроля над потоком загрузки ресурсов. Он позволяет сделать процесс запуска игры более интерактивным и отзывчивым. Для экспериментов попробуйте создать кастомный загрузочный экран, который отображает миниатюры уровней по мере их загрузки, или реализуйте логику, где игровые персонажи появляются на сцене сразу, как только загружены их текстуры и анимации.