О чем этот пример
Загрузка большого количества ресурсов — частая задача в разработке игр. Однако при использовании рендера CANVAS в Phaser можно столкнуться с неожиданными ошибками и падением производительности. В этой статье мы разберем реальный пример из официального репозитория Phaser, который демонстрирует, как организовать тестирование загрузки разного количества изображений и переключаться между версиями движка. Вы научитесь контролировать процесс загрузки, создавать интерактивные меню и анализировать поведение игры при разных условиях.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class SetQuantity extends Phaser.Scene
{
constructor()
{
super();
}
create ()
{
this.add.text(10, 10, `Phaser v${Phaser.VERSION}\n1024 CANVAS TEST\nSelect quantity to load`, { font: '16px Courier', fill: '#00ff00' });
const button1 = this.add.text(10, 100, '10', { fontFamily: 'Arial', fontSize: '24px', color: '#ffffff', align: 'center', fixedWidth: 260, backgroundColor: '#0000cc' });
const button2 = this.add.text(10, 200, '50', { fontFamily: 'Arial', fontSize: '24px', color: '#ffffff', align: 'center', fixedWidth: 260, backgroundColor: '#0000cc' });
const button3 = this.add.text(10, 300, '100', { fontFamily: 'Arial', fontSize: '24px', color: '#ffffff', align: 'center', fixedWidth: 260, backgroundColor: '#0000cc' });
const button4 = this.add.text(10, 400, '250', { fontFamily: 'Arial', fontSize: '24px', color: '#ffffff', align: 'center', fixedWidth: 260, backgroundColor: '#0000cc' });
button1.setPadding(16).setOrigin(0).setInteractive();
button2.setPadding(16).setOrigin(0).setInteractive();
button3.setPadding(16).setOrigin(0).setInteractive();
button4.setPadding(16).setOrigin(0).setInteractive();
button1.once('pointerdown', () => {
this.scene.start('BigLoad', { quantity: 10 });
});
button2.once('pointerdown', () => {
this.scene.start('BigLoad', { quantity: 50 });
});
button3.once('pointerdown', () => {
this.scene.start('BigLoad', { quantity: 100 });
});
button4.once('pointerdown', () => {
this.scene.start('BigLoad', { quantity: 250 });
});
if (Phaser.VERSION === '3.55.2')
{
const button5 = this.add.text(10, 500, 'Swap to 3.61', { fontFamily: 'Arial', fontSize: '24px', color: '#000000', align: 'center', fixedWidth: 260, backgroundColor: '#ffffff' });
button5.setPadding(16).setOrigin(0).setInteractive();
button5.once('pointerdown', () => {
window.location.href = 'https://labs.phaser.io/view.html?src=src/bugs/0000%20big%20load%201024.js&v=live';
});
}
else
{
const button5 = this.add.text(10, 500, 'Swap to 3.55', { fontFamily: 'Arial', fontSize: '24px', color: '#000000', align: 'center', fixedWidth: 260, backgroundColor: '#ffffff' });
button5.setPadding(16).setOrigin(0).setInteractive();
button5.once('pointerdown', () => {
window.location.href = 'https://labs.phaser.io/view.html?src=src/bugs/0000%20big%20load%201024.js&v=3.55.2';
});
}
}
}
class Demo extends Phaser.Scene
{
constructor()
{
super('BigLoad');
}
init (data)
{
this.quantity = data.quantity;
this.add.text(10, 10, `Loading ${this.quantity} 1024px files`, { font: '16px Courier', fill: '#00ff00' });
console.log('Quantity:', this.quantity);
}
preload ()
{
// this.load.setBaseURL('https://cdn.phaserfiles.com/v385');
const progress = this.add.graphics();
this.load.on('progress', value =>
{
progress.clear();
progress.fillStyle(0xffff00, 1);
progress.fillRect(0, 100, 375 * value, 60);
});
for (let i = 0; i < this.quantity; i++)
{
this.load.image(`block${i}`, `https://labs.phaser.io/assets/pics/sao-sinon.png`);
}
}
create ()
{
this.add.image(0, 200, 'block0').setOrigin(0).setScale(0.25);
this.add.image(128, 328, `block${this.quantity - 1}`).setOrigin(0).setScale(0.25);
}
}
const config = {
type: Phaser.CANVAS,
parent: 'phaser-example',
width: 375,
height: 667,
backgroundColor: '#000000',
scene: [ SetQuantity, Demo ]
};
const game = new Phaser.Game(config);
Сцена выбора: создаем меню для тестирования
Класс SetQuantity отвечает за стартовую сцену, где пользователь выбирает, сколько изображений загрузить. Это удобный способ протестировать производительность под разной нагрузкой.
Создаем текстовые элементы, которые будут выполнять роль кнопок. Для этого используется метод this.add.text(). Важно задать стили, чтобы кнопки выглядели как интерактивные элементы.
const button1 = this.add.text(10, 100, '10', { fontFamily: 'Arial', fontSize: '24px', color: '#ffffff', align: 'center', fixedWidth: 260, backgroundColor: '#0000cc' });
После создания текста его нужно сделать интерактивным. Методы setPadding() и setOrigin() задают отступы и точку привязки, а setInteractive() включает обработку событий ввода.
button1.setPadding(16).setOrigin(0).setInteractive();
Обработка нажатия на кнопку реализована через событие 'pointerdown'. Для однократного срабатывания используется once(). При клике сцена запускает основную сцену 'BigLoad' и передает ей выбранное количество через объект данных.
button1.once('pointerdown', () => {
this.scene.start('BigLoad', { quantity: 10 });
});
Динамическое переключение версий Phaser
В примере есть интересная логика для переключения между версиями Phaser 3.55.2 и 3.61. Это полезно для сравнения поведения одного и того же кода в разных сборках движка.
Проверка текущей версии происходит через глобальный объект Phaser.VERSION.
if (Phaser.VERSION === '3.55.2')
В зависимости от результата создается дополнительная кнопка. Ее текст и стили меняются, а при нажатии происходит редирект на другую версию примера на labs.phaser.io.
const button5 = this.add.text(10, 500, 'Swap to 3.61', { fontFamily: 'Arial', fontSize: '24px', color: '#000000', align: 'center', fixedWidth: 260, backgroundColor: '#ffffff' });
button5.once('pointerdown', () => {
window.location.href = 'https://labs.phaser.io/view.html?src=src/bugs/0000%20big%20load%201024.js&v=live';
});
Такой подход позволяет быстро протестировать, исправлена ли определенная проблема в более новой версии движка.
Основная сцена загрузки: инициализация и предзагрузка
Класс Demo (зарегистрированный как 'BigLoad') — это основная рабочая сцена. Она принимает данные из предыдущей сцены через метод init().
init (data)
{
this.quantity = data.quantity;
console.log('Quantity:', this.quantity);
}
Вся логика загрузки ресурсов находится в методе preload(). Здесь создается индикатор прогресса с помощью графического объекта this.add.graphics(). Событие 'progress' объекта this.load позволяет отрисовывать полосу загрузки, обновляя ее при каждом изменении прогресса.
const progress = this.add.graphics();
this.load.on('progress', value =>
{
progress.clear();
progress.fillStyle(0xffff00, 1);
progress.fillRect(0, 100, 375 * value, 60);
});
Загрузка множества изображений организована через цикл for. Каждому изображению присваивается уникальный ключ, но все они загружают один и тот же URL. Это создает искусственную нагрузку для тестирования.
for (let i = 0; i < this.quantity; i++)
{
this.load.image(`block${i}`, `https://labs.phaser.io/assets/pics/sao-sinon.png`);
}
Отображение результата и конфигурация игры
После завершения загрузки управление передается методу create(). В нем отображаются два изображения: первое загруженное (block0) и последнее (block${this.quantity - 1}). Метод setScale(0.25) уменьшает их размер.
create ()
{
this.add.image(0, 200, 'block0').setOrigin(0).setScale(0.25);
this.add.image(128, 328, `block${this.quantity - 1}`).setOrigin(0).setScale(0.25);
}
Конфигурация игры задается в объекте config. Ключевой параметр — type: Phaser.CANVAS, который указывает использовать Canvas рендерер вместо WebGL. Это важно, потому что в данном тесте проверяется именно работа с CANVAS. Размеры игры (width, height) и черный фон (backgroundColor) задают область отрисовки. Массив scene определяет порядок сцен.
const config = {
type: Phaser.CANVAS,
parent: 'phaser-example',
width: 375,
height: 667,
backgroundColor: '#000000',
scene: [ SetQuantity, Demo ]
};
Инициализация игры происходит через создание экземпляра класса Phaser.Game.
const game = new Phaser.Game(config);
Что попробовать дальше
Этот пример наглядно показывает, как организовать тестовый стенд для проверки загрузки ресурсов в Phaser с рендерером CANVAS. Вы можете использовать этот подход для стресс-тестирования своих игр, проверки лимитов загрузки и сравнения производительности между версиями движка. Попробуйте изменить URL загружаемых изображений на свои ассеты, добавить загрузку других типов ресурсов (аудио, JSON) или реализовать более сложный индикатор прогресса с текстовым выводом процентов.
