О чем этот пример
Производительность графики — ключевой фактор для плавного геймплея, особенно в проектах с большим количеством объектов. Пример 'webgl debug.js' демонстрирует не только базовые принципы управления спрайтами, но и встроенные инструменты Phaser для мониторинга производительности в реальном времени. Умение отслеживать FPS и эффективно управлять объектами за пределами камеры — это первый шаг к созданию оптимизированной игры, которая не будет тормозить на слабых устройствах.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
this.donuts = [];
this.fps;
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/grid.png');
this.load.image('donut', 'assets/sprites/donut.png');
}
create ()
{
this.add.image(400, 600, 'bg').setOrigin(0.5, 1);
this.cameras.main.setBounds(0, 0, 800, 600);
for (let i = 0; i < 16; i++)
{
const x = Phaser.Math.Between(0, 800);
const y = Phaser.Math.Between(200, 600);
this.donuts.push(this.add.image(x, y, 'donut'));
}
this.fps = this.add.text(16, 100, 'fps');
}
update ()
{
Phaser.Actions.IncX(this.donuts, -2, -0.5);
Phaser.Actions.WrapInRectangle(this.donuts, this.cameras.main.getBounds(), 128);
this.fps.setText(this.game.renderer.getFps());
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация сцены и загрузка ресурсов
Класс сцены Example расширяет Phaser.Scene. В конструкторе инициализируются два свойства: массив donuts для хранения спрайтов и переменная fps для текстового объекта.
В методе preload задаётся базовый URL для загрузки и загружаются два изображения: фон (bg) и спрайт пончика (donut). Использование setBaseURL упрощает указание путей к ресурсам.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/grid.png');
this.load.image('donut', 'assets/sprites/donut.png');
}
Создание игрового мира и управление камерой
В методе create сначала добавляется фоновое изображение. Важно отметить использование setOrigin(0.5, 1), которое устанавливает точку привязки (anchor) изображения по центру по X и снизу по Y. Это размещает фон внизу сцены.
Затем устанавливаются границы (bounds) для основной камеры (this.cameras.main). Эти границы определяют область, в которой камера может перемещаться, что полезно для скроллинговых игр.
create ()
{
this.add.image(400, 600, 'bg').setOrigin(0.5, 1);
this.cameras.main.setBounds(0, 0, 800, 600);
}
Генерация и анимация объектов
В цикле создаётся 16 спрайтов пончиков. Их начальные координаты X и Y задаются случайным образом с помощью Phaser.Math.Between. Каждый созданный спрайт добавляется в массив this.donuts для последующего управления.
Также создаётся текстовый объект this.fps, который будет отображать текущий FPS. Изначально ему задаётся строка 'fps'.
for (let i = 0; i < 16; i++)
{
const x = Phaser.Math.Between(0, 800);
const y = Phaser.Math.Between(200, 600);
this.donuts.push(this.add.image(x, y, 'donut'));
}
this.fps = this.add.text(16, 100, 'fps');
Обновление состояния и ключевая логика отладки
Метод update выполняется каждый кадр. С помощью Phaser.Actions.IncX всем пончикам в массиве уменьшается координата X на 2, при этом добавляется небольшой случайный разброс в -0.5 пикселя. Это создаёт эффект параллельного скроллинга.
Затем вызывается Phaser.Actions.WrapInRectangle. Эта функция проверяет, находятся ли спрайты в пределах переданного прямоугольника (границ камеры). Если спрайт вышел за его левую границу, он переносится на правую сторону. Это эффективная альтернатива ручной проверке координат для бесконечного фона.
update ()
{
Phaser.Actions.IncX(this.donuts, -2, -0.5);
Phaser.Actions.WrapInRectangle(this.donuts, this.cameras.main.getBounds(), 128);
}
Мониторинг производительности (FPS)
Самая важная для отладки строка — this.game.renderer.getFps(). Этот метод рендерера возвращает текущее количество кадров в секунду. Значение обновляется в текстовом объекте this.fps каждый кадр, позволяя в реальном времени наблюдать за производительность рендеринга WebGL (или Canvas).
Это встроенный инструмент Phaser, который не требует подключения дополнительных библиотек.
this.fps.setText(this.game.renderer.getFps());
Конфигурация и запуск игры
Объект config содержит стандартные настройки игры: автоматический выбор рендерера (WebGL/Canvas), размеры холста, цвет фона, ID родительского HTML-элемента и класс основной сцены.
Игра инициализируется созданием нового экземпляра Phaser.Game с этой конфигурацией.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Этот пример наглядно показывает, как с помощью нескольких строк кода можно организовать движение объектов, управлять их положением относительно камеры и, что критически важно, отслеживать производительность. Для экспериментов попробуйте увеличить количество пончиков в цикле и понаблюдайте за изменением FPS. Или замените WrapInRectangle на Wrap для циклического движения по всем границам экрана. Используйте getFps() во всех своих прототипах, чтобы сразу выявлять проблемы с оптимизацией.
