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

Плавные и реалистичные движения — ключ к качественной анимации в играх. Phaser 3 предлагает мощную систему твинов (tweens), но без правильных функций плавности (easing) движение объектов выглядит механически и скучно. В этой статье мы разберем, как работают три основные функции плавности из семейства Cubic: `in`, `out` и `inOut`. Вы научитесь применять их для создания разнообразных по характеру анимаций — от разгона до замедления.

Версия 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('bg', 'assets/tweens/space.png');
        this.load.image('ufo1', 'assets/tweens/ufo1.png');
        this.load.image('ufo2', 'assets/tweens/ufo2.png');
        this.load.image('ufo3', 'assets/tweens/ufo3.png');
    }

    create ()
    {
        this.add.image(400, 300, 'bg');
        this.add.text(20, 20, 'Cubic Ease').setFontSize(32).setShadow(2, 2);

        this.add.text(750, 70, 'Cubic.in').setShadow(2, 2).setOrigin(1, 0);
        this.add.text(750, 255, 'Cubic.out').setShadow(2, 2).setOrigin(1, 0);
        this.add.text(750, 440, 'Cubic.inOut').setShadow(2, 2).setOrigin(1, 0);

        const ufo1 = this.add.image(100, 140, 'ufo1');
        const ufo2 = this.add.image(100, 325, 'ufo2');
        const ufo3 = this.add.image(100, 510, 'ufo3');

        this.tweens.add({
            targets: ufo1,
            x: 700,
            duration: 2000,
            repeat: -1,
            hold: 500,
            repeatDelay: 500,
            ease: 'cubic.in'
        });

        this.tweens.add({
            targets: ufo2,
            x: 700,
            duration: 2000,
            repeat: -1,
            hold: 500,
            repeatDelay: 500,
            ease: 'cubic.out'
        });

        this.tweens.add({
            targets: ufo3,
            x: 700,
            duration: 2000,
            repeat: -1,
            hold: 500,
            repeatDelay: 500,
            ease: 'cubic.inout'
        });
    }
}

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

const game = new Phaser.Game(config);

Что такое Easing?

Ease-функции (функции плавности) определяют, как изменяется скорость анимации объекта между начальной и конечной точкой. Без них движение было бы линейным: объект двигался бы с одной и той же скоростью от старта до финиша.

Phaser предоставляет множество встроенных ease-функций, и Cubic — одна из них. Она создает более выраженное и естественное ускорение или замедление по сравнению с линейной функцией или, например, Quadratic.

В примере мы видим три разных варианта функции Cubic, примененные к трем одинаковым твинам.

Анатомия твина в Phaser

Перед тем как разбирать ease-функции, посмотрим на базовую конфигурацию твина в методе create(). Все три анимации создаются с помощью this.tweens.add() и имеют одинаковые параметры, кроме ease.

this.tweens.add({
    targets: ufo1,
    x: 700,
    duration: 2000,
    repeat: -1,
    hold: 500,
    repeatDelay: 500,
    ease: 'cubic.in'
});

* targets: Объект или массив объектов для анимации (в нашем случае — спрайт НЛО). * `x`: Целевое свойство и его значение. Объект будет двигаться к X=700. * duration: Длительность одного цикла анимации в миллисекундах (2000 мс = 2 секунды). * repeat: Количество повторений. Значение -1 означает бесконечный повтор. * hold: Пауза (в мс) в конечной точке перед началом следующего действия (например, перед повторением). * repeatDelay: Задержка (в мс) перед началом повторения цикла анимации. * ease: Ключевой параметр. Строка, определяющая функцию плавности. Здесь мы подставляем разные варианты Cubic.

Cubic.in: Плавный разгон

Функция Cubic.in создает эффект плавного разгона объекта с места. Анимация начинается медленно и постепенно набирает скорость к концу движения. Это похоже на то, как трогается тяжелый автомобиль.

ease: 'cubic.in'

В примере это применяется к первому НЛО (ufo1). Обратите внимание, как оно медленно стартует с левого края и резко «приземляется» на правой границе. Этот тип easing отлично подходит для анимации вылета объектов с края экрана или появления элементов интерфейса.

Cubic.out: Плавное замедление

Функция Cubic.out — полная противоположность in. Объект начинает движение резко, с высокой скоростью, а к концу пути плавно и эффектно замедляется, как будто приземляется.

ease: 'cubic.out'

Второе НЛО (ufo2) использует эту функцию. Оно быстро стартует, а под конец движения словно «притормаживает» перед остановкой. Такой easing идеален для анимации попаданий, приземлений или когда объект должен аккуратно встать на нужное место.

Cubic.inOut: Симметричное ускорение и замедление

Функция Cubic.inOut объединяет оба предыдущих эффекта в одной плавной кривой. Движение начинается с плавного разгона, достигает пика скорости в середине пути и так же плавно замедляется к концу.

ease: 'cubic.inout'

**Важно:** Обратите внимание на регистр строки. В коде примера используется строчные буквы ('cubic.inout'), а не 'cubic.inOut'. Phaser поддерживает оба варианта, но стоит быть внимательным к документации конкретной версии.

Третье НЛО (ufo3) демонстрирует этот тип движения. Оно выглядит наиболее естественным и физически обоснованным для многих сценариев, например, для перемещения персонажа из точки А в точку Б.

Запуск и настройка сцены

Весь пример заключен в стандартную структуру проекта Phaser. Обратите внимание на конфигурацию игры, особенно на размеры холста и связь со сценой.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example // Указываем наш класс сцены
};

const game = new Phaser.Game(config);

Метод preload() загружает все необходимые изображения с удаленного ресурса. Фон и спрайты НЛО подготавливаются до создания сцены, что является стандартной практикой в Phaser для избежания «мелькания» незагруженных ассетов.

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

Использование функций плавности — простой, но невероятно мощный инструмент для «оживления» вашей игры. Cubic-функции обеспечивают более драматичные ускорения и замедления, чем их линейные или квадратичные аналоги. **Идеи для экспериментов:** 1. Попробуйте применить разные ease-функции (например, back, elastic, bounce) к одному и тому же твину и наблюдайте за разным «характером» движения. 2. Скомбинируйте ease-функцию с анимацией других свойств: scale, alpha, angle. Представьте, как НЛО не только летит, но и медленно исчезает (alpha: 0) с замедлением (cubic.out). 3. Поэкспериментируйте с параметрами yoyo: true (возврат к начальному состоянию) вместе с разными ease-функциями для создания сложных циклических анимаций.