О чем этот пример
При создании динамических интерфейсов или анимированных текстовых элементов в играх на Phaser важно не только изменять визуальный масштаб объекта, но и понимать, как эти изменения влияют на его физические границы (bounds). Этот пример демонстрирует работу с масштабированием `BitmapText` и визуализацией его фактических размеров, что критически важно для точного позиционирования, обработки столкновений и создания плавных анимаций, взаимодействующих с другими игровыми объектами.
Версия 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.bitmapFont('atari', 'assets/fonts/bitmap/atari-smooth.png', 'assets/fonts/bitmap/atari-smooth.xml');
}
create ()
{
this.string = 'Phaser 3\nBitmapText\nScaling\nwith bounds';
this.text = this.add.bitmapText(0, 0, 'atari', this.string).setFontSize(32);
this.graphics = this.add.graphics({ x: 0, y: 0, lineStyle: { thickness: 1, color: 0xffff00, alpha: 1 } });
this.tweens.add({
targets: this.text,
duration: 4000,
scaleX: 2,
ease: 'Quad.easeInOut',
repeat: -1,
yoyo: true
});
this.tweens.add({
targets: this.text,
duration: 2000,
scaleY: 4,
ease: 'Quad.easeInOut',
repeat: -1,
yoyo: true
});
}
update ()
{
this.text.setText(this.string + '\nScale X: ' + this.text.scaleX.toFixed(4));
this.graphics.clear();
this.graphics.strokeRect(this.text.x, this.text.y, this.text.width, this.text.height);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Загрузка bitmap-шрифта и создание текста
Перед использованием bitmap-шрифта его необходимо загрузить. Этот тип шрифтов состоит из изображения (спрайтшита) и файла описания (обычно XML), что позволяет рендерить текст быстро и без использования системных шрифтов.
В методе preload мы загружаем шрифт 'atari' с указанием путей к PNG и XML файлам. Базовый URL упрощает загрузку из удаленного репозитория.
В методе create создается сам текстовый объект. Ключевой момент — начальная позиция (0, 0) и установка размера шрифта через setFontSize(32). BitmapText использует целочисленные размеры для четкого отображения.
// Загрузка шрифта
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.bitmapFont('atari', 'assets/fonts/bitmap/atari-smooth.png', 'assets/fonts/bitmap/atari-smooth.xml');
// Создание текстового объекта
this.string = 'Phaser 3\nBitmapText\nScaling\nwith bounds';
this.text = this.add.bitmapText(0, 0, 'atari', this.string).setFontSize(32);
Анимация масштабирования с помощью Tween
Для создания плавной анимации трансформаций в Phaser используется система Tweens. В примере создаются два независимых твина, которые управляют масштабировами объекта this.text по осям X и Y с разной длительностью и поведением.
Первый твин за 4 секунды увеличивает scaleX до 2, а затем возвращает к 1. Второй твин работает быстрее (2 секунды) и изменяет scaleY до 4. Параметр yoyo: true заставляет анимацию воспроизводиться в обратном порядке, а repeat: -1 делает ее бесконечной.
// Анимация масштаба по оси X
this.tweens.add({
targets: this.text,
duration: 4000,
scaleX: 2,
ease: 'Quad.easeInOut',
repeat: -1,
yoyo: true
});
// Анимация масштаба по оси Y
this.tweens.add({
targets: this.text,
duration: 2000,
scaleY: 4,
ease: 'Quad.easeInOut',
repeat: -1,
yoyo: true
});
Визуализация границ (Bounds) и обновление текста
Одна из ключевых особенностей примера — демонстрация того, как свойства width и height объекта BitmapText изменяются в реальном времени при масштабировании. Эти свойства возвращают текущие фактические размеры объекта с учетом масштаба, а не исходные размеры шрифта.
В методе update, который вызывается каждый кадр, происходит две важные вещи:
1. Обновляется содержимое текста, чтобы отображать текущее значение scaleX.
2. Перерисовывается желтый прямоугольник (Graphics), обводящий текущие границы текстового объекта.
update ()
{
// Динамическое обновление текста с текущим масштабом
this.text.setText(this.string + '\nScale X: ' + this.text.scaleX.toFixed(4));
// Очистка предыдущей графики и отрисовка нового прямоугольника по границам
this.graphics.clear();
this.graphics.strokeRect(this.text.x, this.text.y, this.text.width, this.text.height);
}
Объект this.graphics создается в create() и служит для отладки, наглядно показывая, как меняется занимаемая объектом область.
Конфигурация игры и инициализация
Код завершается стандартной для Phaser 3 конфигурацией игры. Указывается тип рендерера, размеры холста, ID родительского HTML-элемента и класс основной сцены. После создания экземпляра Phaser.Game с этой конфигурацией игра запускается.
const config = {
type: Phaser.AUTO, // Автовыбор между WebGL и Canvas
width: 800,
height: 600,
parent: 'phaser-example', // ID контейнера в HTML
scene: Example // Главная сцена
};
const game = new Phaser.Game(config);
Что попробовать дальше
Этот пример наглядно показывает, что свойства width и height игровых объектов в Phaser (в данном случае BitmapText) динамически пересчитываются при применении трансформаций, таких как масштабирование. Это фундаментально для точного позиционирования, расчета столкновений (this.physics.add.image) и создания сложных анимаций. Для экспериментов попробуйте
- Привязать анимацию масштаба к вводу игрока (например, клику)
- Добавить физическое тело к тексту и посмотреть, как
width/heightвлияют на коллайдер - Создать несколько масштабируемых текстовых объектов, которые взаимодействуют друг с другом через свои границы
