О чем этот пример
При создании сложных анимаций в Phaser часто требуется выполнить дополнительные действия именно в момент старта tween-анимации. Например, сделать объект видимым, воспроизвести звук или обновить интерфейс. Встроенный коллбэк `onStart` в конфигурации Tween позволяет сделать это точно и без костылей. В этой статье разберем, как правильно настроить и использовать `onStart` и `onStartParams`, чтобы связать запуск анимации с вашей игровой логикой. Это особенно полезно для синхронизации визуальных эффектов с геймплеем.
Версия 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.image('block', 'assets/sprites/block.png');
}
create()
{
var marker = this.add.image(100, 100, 'block').setAlpha(0.3);
var image = this.add.image(100, 100, 'block').setAlpha(0);
var tween = this.tweens.add({
targets: image,
x: 600,
ease: 'Power1',
duration: 3000,
paused: true,
onStart: this.onStartHandler,
onStartParams: [image]
});
this.input.once('pointerdown', function ()
{
tween.play();
});
}
// The callback is always sent a reference to the Tween as the first argument and the targets as the second,
// then whatever you provided in the onStartParams array follows
onStartHandler(tween, targets, gameObject)
{
console.log(arguments);
gameObject.setAlpha(1);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Tween и его жизненный цикл
Tween (или твин) в Phaser — это объект, управляющий плавной анимацией свойств одного или нескольких целевых объектов (targets) за указанное время. У каждого tween есть жизненный цикл с ключевыми событиями, на которые можно подписаться. Одно из таких событий — onStart. Оно срабатывает один раз, непосредственно перед началом интерполяции свойств, даже если tween был запущен из паузы (paused: true).
Это отличает onStart от, например, onActive, который может срабатывать при каждом возобновлении анимации. onStart идеально подходит для одноразовой инициализации, связанной со стартом движения.
Разбор примера: Подготовка сцены и объектов
В примере создается простая сцена с двумя спрайтами — маркером и основным изображением. Маркер полупрозрачный и показывает начальную точку. Основное изображение изначально полностью прозрачное (setAlpha(0)).
preload() {
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('block', 'assets/sprites/block.png');
}
create() {
var marker = this.add.image(100, 100, 'block').setAlpha(0.3);
var image = this.add.image(100, 100, 'block').setAlpha(0);
}
Ключевой момент: tween создается в состоянии паузы (paused: true). Это частая практика, когда анимация должна запуститься по внешнему событию (клику мыши в данном случае).
Конфигурация Tween с коллбэком `onStart`
Коллбэк onStart задается прямо в конфигурационном объекте tween. Вместе с ним через массив onStartParams можно передать дополнительные аргументы, которые будут подставлены в функцию-обработчик после стандартных параметров.
var tween = this.tweens.add({
targets: image, // Целевой объект для анимации
x: 600, // Конечная координата X
ease: 'Power1', // Функция плавности
duration: 3000, // Длительность анимации в миллисекундах
paused: true, // Создать, но не запускать сразу
onStart: this.onStartHandler, // Ссылка на функцию-обработчик
onStartParams: [image] // Дополнительный аргумент для обработчика
});
Обратите внимание: onStartParams — это массив. В данном случае мы передаем в него ссылку на тот же объект image, который является target. Это нужно для удобства доступа внутри обработчика.
Обработчик события и его параметры
Phaser автоматически передает в функцию-обработчик onStart два первых аргумента: ссылку на сам объект tween и массив целевых объектов. Затем идут аргументы из вашего массива onStartParams.
onStartHandler(tween, targets, gameObject) {
console.log(arguments); // Можно посмотреть все переданные аргументы
gameObject.setAlpha(1); // Делаем объект полностью видимым
}
В нашем примере:
1. tween — ссылка на созданный нами tween.
2. targets — массив [image].
3. gameObject — тот самый объект image, который мы передали через onStartParams: [image].
Именно в этот момент, перед началом движения, мы вызываем gameObject.setAlpha(1), чтобы блок стал видимым. Запуск анимации происходит по клику мыши через tween.play().
Запуск анимации по внешнему событию
Tween создан в паузе, поэтому для его старта требуется явный вызов метода play(). В примере это привязано к событию клика (pointerdown).
this.input.once('pointerdown', function () {
tween.play();
});
Использование once гарантирует, что обработчик сработает только при первом клике. При вызове play() сразу же сработает коллбэк onStartHandler, сделав объект видимым, и только затем начнется анимация перемещения к точке x: 600.
Что попробовать дальше
Коллбэк onStart — это мощный и точный инструмент для привязки логики инициализации к началу анимации. Он помогает избежать рассинхронизации, когда код подготовки выполняется до или после tween.play().
**Идеи для экспериментов:**
1. Попробуйте передать в onStartParams не сам объект, а его свойство (например, цвет) и менять его в обработчике.
2. Создайте цепочку tween-ов, где onStart второго tween запускается в onComplete первого, и поэкспериментируйте с передачей данных между ними через параметры.
3. Вместо setAlpha в коллбэке запустите частицу (this.add.particles) в стартовой позиции объекта для создания эффекта появления.
