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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


let image;
let tween;
let text;

class Example extends Phaser.Scene {
    constructor() {
        super();
    }

    preload() {
        
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('makoto', 'assets/pics/makoto.png');
    }

    create() {
        image = this.add.image(400, 300, 'makoto');

        text = this.add.text(10, 10, '', { font: '16px Courier', fill: '#00ff00' });

        tween = this.tweens.add({
            targets: image,
            alpha: {
                from: 0,
                to: 1
            },
            delay: 2000,
            duration: 5000
        });

        /*
        tween = this.tweens.add({
            targets: image,
            alpha: {
                start: 0,
                to: 1
            },
            delay: 2000,
            duration: 6000
        });
        */

        /*
        tween = this.tweens.add({
            targets: image,
            alpha: {
                start: 0.1,
                from: 1,
                to: 0.1
            },
            delay: 2000,
            duration: 2000
        });
        */
    }

    update() {
        if (tween.data) this.debugTweenData(text, tween.data[0]);
    }

    debugTweenData(text, tweenData) {
        var output = [];

        var TDStates = [
            'CREATED',
            'INIT',
            'DELAY',
            'OFFSET_DELAY',
            'PENDING_RENDER',
            'PLAYING_FORWARD',
            'PLAYING_BACKWARD',
            'HOLD_DELAY',
            'REPEAT_DELAY',
            'COMPLETE'
        ];

        output.push(tweenData.key);
        output.push('--------');
        output.push('State: ' + TDStates[tweenData.state]);
        output.push('Start: ' + tweenData.start);
        output.push('Current: ' + tweenData.current);
        output.push('End: ' + tweenData.end);
        output.push('Progress: ' + tweenData.progress);
        output.push('Elapsed: ' + tweenData.elapsed);
        output.push('Duration: ' + tweenData.duration);
        output.push('Total Duration: ' + tweenData.totalDuration);
        output.push('Delay: ' + tweenData.delay);
        output.push('Yoyo: ' + tweenData.yoyo);
        output.push('Hold: ' + tweenData.hold);
        output.push('Repeat: ' + tweenData.repeat);
        output.push('Repeat Counter: ' + tweenData.repeatCounter);
        output.push('Repeat Delay: ' + tweenData.repeatDelay);

        text.setText(output);
    }
}

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

const game = new Phaser.Game(config);

Создание базового твина: от прозрачного к видимому

Ключевой элемент примера — создание твина, который изменяет прозрачность (alpha) изображения от 0 (полностью прозрачно) до 1 (полная видимость).

Этот твин настраивается с помощью объекта конфигурации, передаваемого в метод this.tweens.add(). Давайте посмотрим на его параметры:

tween = this.tweens.add({
    targets: image,
    alpha: {
        from: 0,
        to: 1
    },
    delay: 2000,
    duration: 5000
});

Здесь targets указывает на объект, который нужно анимировать — наше изображение image. Свойство alpha настраивается через вложенный объект, где from — начальное значение, а to — конечное. Параметр delay задает задержку в 2000 мс (2 секунды) перед стартом анимации, а duration определяет длительность самого перехода в 5000 мс (5 секунд).

Зачем нужна функция debugTweenData?

Сам твин работает «из коробки» — изображение плавно появляется. Но пример идет дальше: в каждом кадре (в методе update) он вызывает функцию debugTweenData, чтобы отобразить внутреннее состояние твина.

Функция принимает текстовый объект text для вывода и первый элемент массива tween.data. Этот массив содержит объекты данных для каждого целевого свойства твина (в нашем случае — только для alpha).

if (tween.data) this.debugTweenData(text, tween.data[0]);

Внутри debugTweenData формируется массив строк output, который затем отображается на экране. Это позволяет в реальном времени наблюдать за изменением таких параметров, как прогресс, состояние, задержки и счетчики повторов.

Ключевые свойства TweenData, которые стоит знать

Функция отладки выводит множество свойств объекта tweenData. Давайте разберем самые полезные из них:

* state: Текущее состояние твина (например, DELAY, PLAYING_FORWARD, COMPLETE). Состояния соответствуют константам в массиве TDStates. * progress: Прогресс анимации от 0 (начало) до 1 (конец). Это ключевое значение для расчета промежуточных состояний. * elapsed и duration: Прошедшее время с начала анимации и ее общая длительность. * delay, hold, repeatDelay: Различные типы задержек, которые можно настроить в твине. * repeat и repeatCounter: Общее число повторов и текущий счетчик. * yoyo: Флаг, указывающий, будет ли твин проигрываться в обратном направлении после завершения.

output.push('Progress: ' + tweenData.progress);
output.push('State: ' + TDStates[tweenData.state]);
output.push('Repeat Counter: ' + tweenData.repeatCounter);

Наблюдение за этими свойствами в динамике — лучший способ понять логику работы твинов в Phaser.

Экспериментируем с конфигурацией: закомментированные варианты

В исходном коде есть два закомментированных блока, которые показывают альтернативные способы настройки. Они демонстрируют нюансы работы с параметрами start, from и to.

Первый вариант использует start вместо from. В API Phaser Tweens эти параметры часто синонимичны, но from является более явным и предпочтительным для задания начального значения.

// Вариант 1: Использование 'start'
alpha: {
    start: 0,
    to: 1
},

Второй вариант задает сразу три значения: start, from и to. В этом случае from переопределяет start, и анимация идет от 1 к 0.1, что может быть неочевидно с первого взгляда.

// Вариант 2: Путаница с start, from, to
alpha: {
    start: 0.1,
    from: 1,
    to: 0.1
},

Практический совет: для ясности всегда используйте пару from и to для определения диапазона анимации.

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

Этот пример — отличная отправная точка для глубокого погружения в систему твинов Phaser 3. Используя функцию отладки, вы можете проверять состояние анимаций, точно настраивать цепочки и последовательности. Для экспериментов попробуйте

  1. Добавить параметры repeat, yoyo и hold в конфиг твина и понаблюдать, как меняются repeatCounter и state
  2. Создать несколько твинов для разных свойств (например, `xиscale) и выводить данные для каждого из них, чтобы понять структуру массиваtween.data`
  3. Использовать полученные данные (например, progress) для синхронизации других игровых событий с анимацией