О чем этот пример
Создание плавных анимаций — ключевой элемент игрового процесса, но что делать, когда цель движения меняется прямо во время анимации? Метод `updateTo` объекта твина в Phaser позволяет динамически обновлять свойства анимируемого объекта, сохраняя текущий прогресс анимации. Это особенно полезно для реализации следящих снарядов, реактивного перемещения персонажей или любых интерактивных анимаций, где конечная точка определяется действиями игрока.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
var config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: {
preload: preload,
create: create,
update: update
}
};
var arrow;
var tween;
var text;
var game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('arrow', 'assets/sprites/arrow.png');
}
function create ()
{
text = this.add.text(30, 20, '0', { font: '16px Courier', fill: '#00ff00' });
arrow = this.add.image(400, 300, 'arrow');
tween = this.tweens.add({
targets: arrow,
x: 600,
y: 300,
ease: 'Sine.easeIn',
duration: 2000,
paused: true
});
this.input.on('pointerdown', function () {
tween.updateTo('x', this.input.x, true);
tween.updateTo('y', this.input.y, true);
tween.play();
},this);
}
function update ()
{
arrow.rotation = Math.atan2(this.input.y - arrow.y, this.input.x - arrow.x);
if (tween.isPlaying())
{
text.setText('Progress: ' + tween.progress);
}
else
{
text.setText('Click to start');
}
}
Инициализация сцены и объектов
В примере создаётся базовая сцена Phaser с предзагрузкой ресурсов и инициализацией объектов. Мы загружаем спрайт стрелки, который будет служить нашим анимируемым объектом.
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('arrow', 'assets/sprites/arrow.png');
}
В функции create создаются основные элементы: текстовое поле для отображения прогресса и сам спрайт стрелки. Ключевым моментом является создание твина с флагом paused: true, что означает, что анимация не начнётся автоматически.
function create ()
{
text = this.add.text(30, 20, '0', { font: '16px Courier', fill: '#00ff00' });
arrow = this.add.image(400, 300, 'arrow');
tween = this.tweens.add({
targets: arrow,
x: 600,
y: 300,
ease: 'Sine.easeIn',
duration: 2000,
paused: true
});
}
Обработка ввода и динамическое обновление твина
Механика примера активируется по клику мыши. При каждом клике вызывается обработчик события pointerdown, который использует метод updateTo для изменения целевых значений твина.
this.input.on('pointerdown', function () {
tween.updateTo('x', this.input.x, true);
tween.updateTo('y', this.input.y, true);
tween.play();
}, this);
Метод tween.updateTo() принимает три аргумента: имя обновляемого свойства (например, 'x'), новое целевое значение (координата курсора) и булевый флаг immediate. Установка immediate в true означает, что изменение применится мгновенно к текущему значению свойства, и анимация продолжится уже к новой цели с того места, где она была остановлена. Если бы флаг был false, изменение цели вступило бы в силу только при следующем запуске твина.
Расчёт вращения и отображение прогресса
В функции update, которая вызывается на каждом кадре, происходит две важные операции. Во-первых, вычисляется и устанавливается угол поворота стрелки так, чтобы она всегда была направлена в сторону текущей позиции курсора. Это создаёт эффект прицеливания.
function update ()
{
arrow.rotation = Math.atan2(this.input.y - arrow.y, this.input.x - arrow.x);
}
Во-вторых, в зависимости от состояния твина обновляется текстовое поле. Если твин активен (tween.isPlaying() возвращает true), отображается текущий прогресс анимации от 0 до 1. В противном случае показывается инструкция для пользователя.
if (tween.isPlaying())
{
text.setText('Progress: ' + tween.progress);
}
else
{
text.setText('Click to start');
}
}
Ключевые API и свойства
Для работы с динамическими твинами в этом примере используются следующие методы и свойства Phaser:
- this.tweens.add(): Создаёт и добавляет новый твин в менеджер анимаций сцены.
- tween.updateTo(property, value, immediate): Основной метод для динамического изменения цели анимации.
- tween.progress: Текущий прогресс анимации в диапазоне от 0 (начало) до 1 (конец).
- tween.isPlaying(): Проверяет, активен ли твин в данный момент.
- tween.play(): Запускает или возобновляет воспроизведение приостановленного твина.
Важно, что метод updateTo не перезапускает анимацию с начала, а модифицирует её параметры "на лету", что и является его главным преимуществом.
Что попробовать дальше
Метод updateTo открывает возможности для создания отзывчивых и интерактивных анимаций, где конечное состояние может меняться в реальном времени. Для экспериментов попробуйте изменить параметр immediate на false и посмотрите на разницу в поведении, примените метод к другим свойствам, например scale или alpha, или создайте цепочку твинов, где последующий твин динамически подстраивается под результат предыдущего.
