О чем этот пример
В Phaser анимации спрайтов часто управляются автоматически, но для создания плавных UI-индикаторов, синхронизации событий или нелинейных скриптовых последовательностей нужно точно знать, на каком этапе воспроизведения находится клип. Метод `anims.getProgress()` предоставляет нормализованное значение от 0 до 1, отражающее текущий прогресс анимации, независимо от её длины или сложности. В этой статье разберём, как использовать этот метод для визуализации прогресса и интеграции его в игровую логику.
Версия 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.atlas('gems', 'assets/animations/diamond.png', 'assets/animations/diamond.json');
}
create ()
{
this.anims.create({
key: 'diamond',
frames: this.anims.generateFrameNames('gems', { prefix: 'diamond_', end: 15, zeroPad: 4 }),
frameRate: 16,
yoyo: true,
repeat: -1,
repeatDelay: 300
});
// this.gem is a local variable.
this.gem = this.add.sprite(400, 480, 'gems')
.play('diamond').setScale(4);
this.debug = this.add.graphics();
}
update ()
{
this.debug.clear();
const size = 672;
this.debug.fillStyle(0x2d2d2d);
this.debug.fillRect(64, 64, size, 48);
this.debug.fillStyle(0x2dff2d);
this.debug.fillRect(64, 64, size * this.gem.anims.getProgress(), 48);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
pixelArt: true,
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка анимации и спрайта
В первую очередь необходимо создать и запустить анимацию на спрайте. В примере используется атлас gems с кадрами, названными по шаблону.
this.anims.create({
key: 'diamond',
frames: this.anims.generateFrameNames('gems', { prefix: 'diamond_', end: 15, zeroPad: 4 }),
frameRate: 16,
yoyo: true,
repeat: -1,
repeatDelay: 300
});
this.gem = this.add.sprite(400, 480, 'gems')
.play('diamond').setScale(4);
Анимация diamond создаётся с помощью this.anims.create. Параметр yoyo: true заставляет анимацию проигрываться в обратном порядке после завершения прямого цикла, repeat: -1 задаёт бесконечное повторение, а repeatDelay: 300 добавляет задержку в 300 миллисекунд между повторами. Спрайт this.gem создаётся в позиции (400, 480), ему назначается анимация diamond, и он масштабируется в 4 раза для наглядности.
Получение прогресса анимации
Ключевой метод для отслеживания — anims.getProgress(), вызываемый у компонента анимации спрайта. Он возвращает число от 0 (начало анимации) до 1 (её завершение).
const progress = this.gem.anims.getProgress();
Это значение обновляется каждый кадр, даже если анимация зациклена или использует эффект yoyo. Для анимаций с repeat: -1 прогресс будет циклически меняться от 0 до 1. Важно: getProgress() всегда возвращает прогресс текущего цикла, а не всей последовательности повторов.
Визуализация прогресса через графику
В методе update() каждый кадр очищается и перерисовывается индикатор прогресса. Используется графика this.debug для отрисовки двух прямоугольников: фона и заполняемой части.
update ()
{
this.debug.clear();
const size = 672;
this.debug.fillStyle(0x2d2d2d);
this.debug.fillRect(64, 64, size, 48);
this.debug.fillStyle(0x2dff2d);
this.debug.fillRect(64, 64, size * this.gem.anims.getProgress(), 48);
}
Сначала this.debug.clear() удаляет предыдущую графику. Затем рисуется тёмно-серый фон (0x2d2d2d) фиксированного размера. Поверх него рисуется зелёный (0x2dff2d) прямоугольник, ширина которого вычисляется как size * this.gem.anims.getProgress(). Таким образом, зелёная полоса расширяется и сжимается в точном соответствии с прогрессом анимации алмаза.
Практическое применение в играх
Отслеживание прогресса анимации полезно не только для дебага. Вот несколько реальных сценариев:
- **Синхронизация звуков или эффектов**: воспроизводить звук шага, когда прогресс анимации ходьбы достигает 0.5. - **Прогресс-бары заклинаний**: визуализировать длительность каста способности. - **Плавное управление камерой**: привязать движение камеры к прогрессу анимации перехода между локациями. - **Событийные триггеры**: выполнять код (например, наносить урон) в определённый момент анимации атаки.
if (this.player.anims.getProgress() > 0.7 && !this.attackTriggered) {
this.applyDamage();
this.attackTriggered = true;
}
Что попробовать дальше
Метод anims.getProgress() — это простой и мощный инструмент для связи визуальной анимации с игровой логикой. Он позволяет создавать отзывчивые интерфейсы и сложные последовательности действий. Попробуйте экспериментировать: привяжите прогресс анимации к изменению прозрачности спрайта, управлению частицами или генерации процедурной анимации для UI-элементов.
