О чем этот пример
Анимация объектов — основа динамики в играх. Часто недостаточно просто переместить спрайт — нужно запустить следующее действие: изменить его состояние, воспроизвести звук или начать новую анимацию. Колбэк `onComplete` в системе твинов Phaser решает эту задачу элегантно, позволяя связать завершение анимации с любой логикой вашей игры. В этой статье разберем, как настроить такой колбэк и передать в него параметры для гибкого управления геймплеем.
Версия 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, 300, 'block').setAlpha(0.3);
var image = this.add.image(100, 300, 'block');
this.tweens.add({
targets: image,
x: 600,
ease: 'Power1',
duration: 3000,
onComplete: this.onCompleteHandler,
onCompleteParams: [image]
});
}
// The callback is always sent a reference to the Tween as the first argument and the targets as the second.
// Whatever you provided in the onCompleteParams array follows.
onCompleteHandler(tween, targets, myImage)
{
console.log('onCompleteHandler');
myImage.setScale(2);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое твин и его колбэк onComplete
Твин (tween) в Phaser — это объект, управляющий плавным изменением свойств цели (например, позиции, прозрачности, масштаба) за заданное время. Метод this.tweens.add() создает и запускает такой твин.
Колбэк onComplete — это функция, которую вы указываете в конфигурации твина. Движок автоматически вызовет ее один раз, когда анимация полностью завершится. Это идеальный момент для выполнения пост-обработки.
Создание базовой анимации с колбэком
Рассмотрим код из примера. В методе create() сцены создаются два спрайта — маркер и подвижное изображение. Для подвижного изображения настраивается твин, который за 3 секунды переместит его по оси X.
Ключевой параметр — onComplete. В него передается ссылка на метод класса сцены this.onCompleteHandler. Phaser вызовет этот метод, когда блок достигнет координаты x=600.
this.tweens.add({
targets: image,
x: 600,
ease: 'Power1',
duration: 3000,
onComplete: this.onCompleteHandler, // Указываем функцию-обработчик
onCompleteParams: [image] // Передаем параметры для обработчика
});
Функция-обработчик и ее параметры
Функция onCompleteHandler объявлена как метод сцены. Phaser всегда вызывает ее с определенными аргументами.
* **Первый аргумент (tween)**: ссылка на сам объект твина, который завершился. Полезно, если нужно его перезапустить или остановить другие связанные твины.
* **Второй аргумент (targets)**: массив целей, к которым был применен твин. В нашем случае это массив с одним элементом — спрайтом image.
* **Последующие аргументы**: значения, которые вы сами передали в массиве onCompleteParams. В примере мы передали [image], поэтому третьим аргументом (myImage) придет тот же спрайт.
// The callback is always sent a reference to the Tween as the first argument and the targets as the second.
// Whatever you provided in the onCompleteParams array follows.
onCompleteHandler(tween, targets, myImage)
{
console.log('onCompleteHandler');
// Меняем масштаб переданного спрайта
myImage.setScale(2);
}
Внутри обработчика мы используем переданный спрайт myImage и метод setScale(2), чтобы увеличить блок в два раза сразу после завершения движения.
Почему важно передавать параметры явно
Вы могли бы обратиться к спрайту image напрямую, если бы он был сохранен в переменной класса. Однако явная передача через onCompleteParams делает код более универсальным и надежным.
Представьте, что у вас несколько анимаций для разных объектов, завершающихся одним обработчиком. Параметры позволяют понять, с каким именно объектом нужно работать. Это также помогает избежать проблем с областью видимости (this), если бы вы использовали стрелочную функцию.
// Плохо: обработчик "зашит" на одну конкретную переменную.
onCompleteHandler() {
image.setScale(2); // А если image недоступен здесь?
}
// Хорошо: обработчик получает объект для работы как параметр.
onCompleteHandler(tween, targets, targetImage) {
targetImage.setScale(2); // Работает для любого переданного спрайта.
}
Практические идеи для использования
Колбэк onComplete открывает множество возможностей для геймдизайна:
* **Цепочка анимаций**: В колбэке первого твина запускайте второй, создавая сложные последовательности.
* **Управление состоянием**: Помечайте объект как "достигший цели", что может запустить проверку условий победы.
* **Визуальные и звуковые эффекты**: Воспроизведите частицы взрыва (`this.add.particles`) или звук (`this.sound.play`) при завершении движения.
* **Активация физики**: После плавного появления "включите" физику для объекта с помощью `this.physics.add.existing(image)`.
onCompleteHandler(tween, targets, targetImage) {
// Запуск звукового эффекта
this.sound.play('pickup');
// Создание частиц в позиции объекта
this.add.particles(targetImage.x, targetImage.y, 'particleTexture', { /* конфиг */ });
// Уничтожение объекта после анимации
targetImage.destroy();
}
*Примечание: чтобы использовать this.sound или this.add внутри обработчика, убедитесь, что контекст this привязан правильно. В примере это работает, потому что обработчик — метод сцены, а в колбэк передается тот же this.*
Что попробовать дальше
Колбэк onComplete — это мощный и простой инструмент для синхронизации игровой логики с анимацией. Он превращает линейное движение в событие, которое может запускать любые последующие действия в игре. Для экспериментов попробуйте создать каскад твинов, где завершение одного запускает следующий, или свяжите колбэк с системой событий (this.events) сцены для более сложной архитектуры.
