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

Создание визуально приятной анимации — ключ к захватывающему геймплею. Прямолинейное движение объектов выглядит неестественно и скучно. В этой статье мы разберем, как использовать easing-функции (функции плавности) в Phaser для придания анимациям инерции, упругости и реализма на примере класса `Quad`. Вы научитесь контролировать ускорение и замедление объектов, что сразу повысит качество вашей игры.

Версия 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, 'Quad Ease').setFontSize(32).setShadow(2, 2);

        this.add.text(750, 70, 'Quad.in').setShadow(2, 2).setOrigin(1, 0);
        this.add.text(750, 255, 'Quad.out').setShadow(2, 2).setOrigin(1, 0);
        this.add.text(750, 440, 'Quad.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: 'quad.in'
        });

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

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

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

const game = new Phaser.Game(config);

Что такое Easing и зачем он нужен?

Easing-функции (от англ. 'to ease' — смягчать) определяют, как изменяется скорость анимации со временем. Вместо равномерного движения из точки А в точку Б объект может плавно разгоняться в начале (in), замедляться в конце (out) или делать и то, и другое (inOut). Это делает движение более естественным, похожим на движение в реальном мире под действием инерции.

В Phaser easing указывается в свойстве ease конфигурации твина. Функция 'quad' — одна из базовых, она описывает квадратичную зависимость, создающую заметное, но мягкое ускорение или замедление.

Анализ примера: Загрузка и создание сцены

Код начинается с загрузки ресурсов в методе preload. Обратите внимание на использование this.load.setBaseURL — это удобный способ указать общий путь для всех последующих загрузок.

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');

В методе create сначала добавляется фон и текстовые подписи с помощью this.add.image и this.add.text. Три НЛО создаются как отдельные объекты-изображения, которые станут целями для анимации.

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

Создание твинов с разными типами Quad Ease

Сердце примера — создание трех анимаций с помощью this.tweens.add. Каждая настраивает движение одного НЛО по горизонтали (x: 700) за 2000 миллисекунд. Ключевое отличие — в свойстве ease.

this.tweens.add({
    targets: ufo1,
    x: 700,
    duration: 2000,
    repeat: -1, // Бесконечное повторение
    hold: 500,  // Пауза в конечной точке
    repeatDelay: 500, // Пауза перед повторением
    ease: 'quad.in' // Плавное ускорение в начале
});

- ease: 'quad.in': НЛО медленно стартует и плавно разгоняется. Эффект "разбега". - ease: 'quad.out': НЛО движется с постоянной скоростью большую часть пути, а затем плавно и быстро останавливается. Эффект "торможения". - ease: 'quad.inout': Комбинация двух предыдущих. Объект плавно разгоняется в первой половине пути и плавно замедляется во второй. Наиболее естественное движение.

Параметры управления анимацией: repeat, hold, repeatDelay

Помимо плавности, пример показывает мощные инструменты управления временной шкалой анимации.

repeat: -1,
hold: 500,
repeatDelay: 500

- repeat: -1 — устанавливает бесконечный цикл повторения анимации. Можно задать любое положительное число для конечного количества повторов. - hold: 500 — объект будет "удерживаться" в конечной точке (при x=700) в течение 500 мс перед началом следующего цикла. Это создает паузу в крайнем положении. - repeatDelay: 500 — добавляет дополнительную задержку в 500 мс *после* паузы hold и *перед* началом следующего цикла анимации (возвратом к начальному состоянию). В данном примере возврат мгновенный, так как не задано свойство yoyo, поэтому repeatDelay работает после паузы hold перед стартом с начала.

Эти параметры позволяют создавать сложные паттерны движения без написания дополнительной логики.

Конфигурация игры и запуск

Финальная часть кода — стандартная конфигурация экземпляра игры Phaser.Game. Ключевой момент здесь — передача нашего класса Example в свойство scene конфига.

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

const game = new Phaser.Game(config);

Свойство parent указывает ID HTML-элемента, в который будет встроен canvas игры. Если элемент с таким ID не найден, canvas будет просто добавлен в тело документа.

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

Использование easing-функций — простой, но невероятно эффективный способ "оживить" вашу игру. Всего одна строка с ease превращает механическое перемещение в выразительную анимацию. Для экспериментов попробуйте заменить 'quad' на другие встроенные функции: 'sine' для более плавного эффекта, 'back' для небольшого "разгона" за пределы целевой точки или 'bounce' для игривых подпрыгиваний. Также изучите режим yoyo: true, который автоматически проигрывает анимацию в обратном порядке, создавая движение туда-обратно.