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

Библиотека твинов в 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 image = this.add.image(100, 100, 'block');

        this.tweens.add({

            targets: image,

            x: { value: 700, duration: 4000, ease: 'Power2', delay: 500 },

            y: { value: 400, duration: 1500, ease: 'Bounce.easeOut' },

            scaleX: { value: 1.5, duration: 2000, delay: 2000, yoyo: true },

            scaleY: { value: 4, duration: 2000, delay: function (target, key, value, targetIndex) { return 1000 + Math.random() * 2000 }, yoyo: true },

            delay: 1000

        });

    }
}

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

const game = new Phaser.Game(config);

Базовая настройка сцены и загрузка

Код начинается с классической структуры сцены Phaser. В методе preload загружается один спрайт — цветной блок. Важно отметить, что базовый URL задается для удобства, чтобы загрузить ассет из репозитория примеров Phaser.

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

В методе create создается экземпляр изображения в точке (100, 100). Этот объект и станет целью нашей анимации.

create() {
    var image = this.add.image(100, 100, 'block');
}

Создание твина с несколькими целями

Анимация создается с помощью this.tweens.add(). Ключевой параметр targets указывает, какой объект (или массив объектов) нужно анимировать. В нашем случае это один спрайт image.

this.tweens.add({
    targets: image,
});

Глобальная задержка для всего твина задается параметром delay: 1000. Это значит, что все анимации свойств начнутся только через 1 секунду после запуска твина, но каждая из них может иметь свою дополнительную задержку.

Объектный синтаксис для свойств анимации

Вместо простых значений, свойствам `x,y,scaleXиscaleYпередаются объекты конфигурации. Это позволяет задавать для каждого свойства уникальные параметры: конечное значение (value), длительность (duration), функцию плавности (ease) и задержку (delay`).

x: { value: 700, duration: 4000, ease: 'Power2', delay: 500 },

Здесь свойство `xначнет меняться через 500 мс после *глобальной* задержки в 1000 мс (итого 1500 мс). Движение до 700 пикселей займет 4 секунды с плавностьюPower2`.

y: { value: 400, duration: 1500, ease: 'Bounce.easeOut' },

Свойство `yначнет анимацию без дополнительной задержки (только глобальные 1000 мс). Оно достигнет значения 400 за 1.5 секунды с "пружинящим" эффектомBounce.easeOut`.

Сложные задержки и эффект йо-йо

Для свойств масштаба используются более продвинутые техники. Параметр yoyo: true заставляет анимацию проигрываться в обратном направлении после завершения, возвращая свойство к начальному значению.

scaleX: { value: 1.5, duration: 2000, delay: 2000, yoyo: true },

Увеличение масштаба по X начнется через 2 секунды после глобальной задержки, продлится 2 секунды, а затем за 2 секунды вернется к 1.

Самая интересная настройка — у scaleY. Его задержка задается не числом, а функцией. Phaser вызывает эту функцию для каждого цели (target) и каждого свойства (key), позволяя вычислить уникальную задержку.

scaleY: { 
    value: 4, 
    duration: 2000, 
    delay: function (target, key, value, targetIndex) { 
        return 1000 + Math.random() * 2000 
    }, 
    yoyo: true 
},

Функция возвращает случайное число от 1000 до 3000 мс. Это означает, что если бы мы анимировали несколько спрайтов, каждый из них начал бы масштабироваться по Y в случайный момент времени в этом интервале, создавая "волнообразный" эффект.

Итоговая конфигурация игры

Код завершается стандартной конфигурацией игры Phaser, где указывается наша сцена Example.

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

Эта конфигурация создает игровое поле размером 800x600 с темно-серым фоном и запускает описанную логику сцены.

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

Использование объектного синтаксиса для свойств в твинах Phaser открывает двери для создания сложных, многослойных анимаций с полным контролем над временной шкалой каждого параметра. Вы можете легко комбинировать задержки, длительности, функции плавности и эффекты вроде yoyo. **Идеи для экспериментов:** 1. Добавьте анимацию свойства alpha (прозрачности) с собственной задержкой. 2. Сделайте цель (targets) массивом из нескольких спрайтов и понаблюдайте за работой функции задержки для scaleY. 3. Поэкспериментируйте с другими функциями плавности (ease) из документации Phaser для каждого свойства, чтобы добиться уникального "чувства" анимации. 4. Попробуйте добавить параметр repeat для создания циклических анимаций.