О чем этот пример
При разработке игр часто возникают ситуации, когда анимацию нужно поставить на паузу и затем возобновить с того же места. Например, когда игрок открывает инвентарь или игру прерывает системное уведомление. Стандартные твины в Phaser при остановке сбрасывают свой прогресс, что может нарушить геймплей. В этой статье мы разберем, как свойство `persist` позволяет создавать "резиновые" анимации, которые запоминают свое состояние и могут быть безопасно возобновлены в любой момент. Это ключ к созданию отзывчивых и плавных игровых сцен.
Версия 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');
var tween = this.tweens.chain({
// paused: true,
persist: true,
tweens: [{
targets: image,
x: 700,
delay: 1000,
duration: 6000,
ease: 'Power2'
}]
});
var toggle = false;
this.input.on('pointerdown', function ()
{
if (toggle) {
tween.stop();
} else {
tween.play();
}
toggle = !toggle;
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Проблема: "Хрупкие" анимации
По умолчанию, если вы остановите твин в Phaser с помощью метода .stop(), а затем попробуете запустить его снова через .play(), анимация начнется с самого начала. Это происходит потому, что внутреннее состояние твина (его прогресс) сбрасывается при остановке.
Представьте анимацию медленно движущегося фона. Игрок нажимает паузу, а при возобновлении фон резко "перепрыгивает" в начальную позицию. Это ломает immersion и выглядит как баг. Именно эту проблему решает флаг persist.
Решение: Волшебный флаг `persist`
Свойство persist указывает менеджеру твинов Phaser не уничтожать объект твина после его завершения (или остановки) и, что более важно, сохранять его текущее внутреннее состояние.
В исходном коде примера мы создаем цепочку твинов (chain) с этим флагом. Хотя в цепочке всего один твин, принцип работы persist от этого не меняется.
var tween = this.tweens.chain({
persist: true,
tweens: [{
targets: image,
x: 700,
delay: 1000,
duration: 6000,
ease: 'Power2'
}]
});
Ключевая строка здесь — persist: true. Без этого флага, вызов tween.stop() сделал бы последующий tween.play() бесполезным.
Механика управления: Play/Stop по клику
В примере реализовано простое переключение состояния анимации по клику мыши. Это наглядно демонстрирует работу persist.
Сначала мы создаем флаг toggle для отслеживания текущего состояния. Затем вешаем обработчик события pointerdown на всю сцену.
var toggle = false;
this.input.on('pointerdown', function ()
{
if (toggle) {
tween.stop();
} else {
tween.play();
}
toggle = !toggle;
});
Логика проста: первый клик запускает твин (tween.play()), второй — останавливает (tween.stop()), третий — снова возобновляет. Благодаря persist: true, каждый новый вызов play() продолжает анимацию ровно с того кадра, на котором она была остановлена. Без этого флага второй и последующие клики play() ничего бы не делали, так как твин был бы помечен как завершенный и удален из системы.
Разбор конфигурации Tween
Давайте подробнее посмотрим на параметры самого твина, чтобы понять, какую анимацию мы контролируем.
{
targets: image, // Объект для анимации (спрайт 'block')
x: 700, // Конечная координата X (движение вправо)
delay: 1000, // Задержка перед стартом (1 секунда)
duration: 6000, // Продолжительность анимации (6 секунд)
ease: 'Power2' // Функция плавности (ускорение в начале)
}
Спрайт image начинает движение с координаты X=100 и за 6 секунд (после секундной задержки) плавно ускоряясь (Power2) до координаты X=700. Спрайт marker, добавленный с прозрачностью (setAlpha(0.3)), просто отмечает стартовую точку для наглядности. Управление, которое мы реализовали, позволяет прервать и продолжить это 6-секундное путешествие в любой момент.
Что попробовать дальше
Свойство persist — это мощный инструмент для создания управляемых, "живучих" анимаций в Phaser. Оно незаменимо для реализации паузы, прерываемых cut-scene или любых анимаций, которые должны реагировать на действия игрока, не сбрасывая прогресс.
**Идеи для экспериментов:**
1. Попробуйте создать цепочку из нескольких твинов с persist: true и управлять ею. Остановится ли вся цепочка или только активный твин?
2. Добавьте в обработчик клика вызов tween.resume() и tween.pause(). Как их поведение отличается от play()/stop() в данном контексте?
3. Свяжите управление анимацией не с кликом, а с другим игровым событием, например, с отдалением камеры или открытием диалогового окна.
