О чем этот пример

Анимация — это душа игрового мира, и Phaser предлагает мощный инструмент для её создания: систему твинов. Часто игровому объекту нужно выполнить не одно, а последовательность движений — плавно проехать по маршруту, сделать комбо-прыжок или нарисовать сложную траекторию. Ручное управление несколькими анимациями быстро становится громоздким. В этой статье мы разберём метод `tweens.chain()`, который позволяет создавать цепочки анимаций, где каждый следующий твин начинается после завершения предыдущего. Это делает код чище, логику — понятнее, а анимации — бесшовными.

Версия 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 ()
    {
        const image = this.add.image(100, 100, 'block');

        this.text = this.add.text(16, 16).setFontSize(16).setColor('#ffffff');

        this.tween = this.tweens.chain({
            targets: image,
            persist: true,
            tweens: [
                {
                    x: 600,
                    ease: 'Linear',
                    duration: 1000,
                },
                {
                    y: 500,
                    ease: 'Linear',
                    duration: 500
                },
                {
                    x: 100,
                    ease: 'Linear',
                    duration: 1000
                },
                {
                    y: 100,
                    ease: 'Linear',
                    duration: 500
                },
            ]
        });
    }

    update ()
    {
        const t = this.tween;

        this.text.setText([
            `Duration: ${t.currentTween.duration}`,
            `Start Delay: ${t.currentTween.startDelay}`,
            `Elapsed: ${t.currentTween.elapsed}`,
            `Progress: ${t.currentTween.progress}`,
            `State: ${t.state}`
        ]);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Что такое цепочка твинов и зачем она нужна

Цепочка твинов (tween chain) — это последовательность анимаций, применённых к одному или нескольким целям (targets). Ключевое отличие от запуска нескольких независимых твинов в том, что они выполняются строго друг за другом, образуя единый поток. Это идеально для:

* Создания патрульных маршрутов для NPC. * Реализации сложных эффектов (например, объект увеличивается, затем вращается и меняет цвет). * Построения сценариев движения, где важна последовательность.

Метод this.tweens.chain() принимает объект конфигурации, который определяет цели и массив (tweens) с описанием каждого шага анимации.

Разбираем конфигурацию цепочки

В примере мы создаём цепочку для спрайта image. Обратите внимание на параметр persist: true. Он указывает системе твинов не уничтожать данные анимации после её завершения, что критически важно для работы отладочной информации в методе update().

Каждый элемент массива tweens — это конфиг для отдельного твина. Здесь цепочка описывает прямоугольный маршрут: вправо, вниз, влево, вверх.

this.tween = this.tweens.chain({
    targets: image,
    persist: true, // Сохраняем твин для отладки
    tweens: [
        { x: 600, ease: 'Linear', duration: 1000 },
        { y: 500, ease: 'Linear', duration: 500 },
        { x: 100, ease: 'Linear', duration: 1000 },
        { y: 100, ease: 'Linear', duration: 500 },
    ]
});

Каждый твин в цепочке — это самостоятельная анимация со своими свойствами (`x,y), длительностью (duration) и функцией сглаживания (ease`). Система автоматически запускает следующий твин, когда текущий завершён.

Мониторинг состояния цепочки в реальном времени

Одна из сильных сторон примера — демонстрация отладки. В методе update() мы в реальном времени выводим ключевые параметры текущего активного твина в цепочке. Это возможно благодаря тому, что метод chain() возвращает объект TweenChain, который содержит ссылку на текущий выполняемый твин (currentTween).

update ()
{
    const t = this.tween;
    this.text.setText([
        `Duration: ${t.currentTween.duration}`,
        `Start Delay: ${t.currentTween.startDelay}`,
        `Elapsed: ${t.currentTween.elapsed}`,
        `Progress: ${t.currentTween.progress}`,
        `State: ${t.state}`
    ]);
}

* currentTween.duration / elapsed / progress: показывают длительность, прошедшее время и прогресс (от 0 до 1) именно того твина, который сейчас играет. * t.state: отображает общее состояние всей цепочки (например, PLAYING, PAUSED).

Такой подход незаменим при тонкой настройке времени и отладке сложных анимационных сценариев.

Что попробовать дальше

Метод tweens.chain() — это элегантное решение для создания последовательных, управляемых анимаций. Он избавляет от необходимости вручную отслеживать события завершения твинов и запускать новые, инкапсулируя всю логику последовательности в одном месте. **Идеи для экспериментов:** 1. Добавьте разные функции ease (например, 'Bounce', 'Back') в каждый шаг цепочки, чтобы движение стало более "живым". 2. Создайте цепочку, которая меняет не только позицию (`x,y), но и масштаб (scale), угол поворота (angle) и прозрачность (alpha`) объекта. 3. Реализуйте систему патрулирования для врага, зациклив цепочку с помощью loop: -1 в конфигурации основного цепочного твина. 4. Используйте цепочку для построения визуальной траектории снаряда с учетом гравитации (последовательные изменения по `y`).