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

Плавные движения — основа визуального восприятия игры. Phaser предлагает мощную систему твинов, которая позволяет анимировать свойства объектов с различными эффектами плавности (easing). В этой статье мы разберем, как использовать один из самых выразительных и 'игровых' типов easing — Bounce. Он имитирует отскок мяча, придавая анимации ощущение веса, упругости и физической достоверности, что идеально подходит для персонажей, предметов или UI-элементов, которые должны привлекать внимание. Вы научитесь применять три его вариации (`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, 'Bounce Ease').setFontSize(32).setShadow(2, 2);

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

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

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

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 для загрузки уже задан, что удобно для примеров.

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 мы сначала размещаем фон и текстовые метки, которые объясняют, какой тип Bounce будет использоваться для каждого объекта. Для позиционирования текста справа используется метод .setOrigin(1, 0), который выравнивает текст по правому краю.

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

    this.add.text(750, 70, 'Bounce.in').setShadow(2, 2).setOrigin(1, 0);
    this.add.text(750, 255, 'Bounce.out').setShadow(2, 2).setOrigin(1, 0);
    this.add.text(750, 440, 'Bounce.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');
    // ... твины будут созданы далее
}

Создание твина с эффектом Bounce.in

Первый твин применяется к объекту ufo1 с параметром ease: 'bounce.in'. Этот тип easing создает эффект, при котором объект начинает движение с серии небольших отскоков, как будто он падает на землю, а затем переходит в плавное движение. Анимация начинается с 'упругого' старта.

Ключевые параметры конфигурации: * targets: объект или массив объектов для анимации. * `x`: 700 — конечная координата по оси X. * duration: 2000 — длительность одного цикла анимации в миллисекундах. * repeat: -1 — бесконечное повторение. * hold: 500 — пауза в конце каждого цикла, перед началом повторения. * repeatDelay: 500 — дополнительная пауза перед повторением.

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

Создание твина с эффектом Bounce.out

Второй твин использует ease: 'bounce.out'. Это противоположность первому варианту. Объект ufo2 движется плавно, а завершает свою анимацию серией отскоков, словно приземляясь на поверхность. Этот эффект отлично подходит для завершающих действий, например, когда предмет падает на пол.

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

Создание твина с эффектом Bounce.inOut

Третий твин, с ease: 'bounce.inout', комбинирует оба предыдущих эффекта. Объект ufo3 начинает движение с отскоков и заканчивает отскоками, создавая полный цикл 'упругого' движения. Обратите внимание на написание в нижнем регистре: 'bounce.inout'. Эта вариация наиболее полно имитирует поведение прыгающего мяча.

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

Настройка игры и запуск

Финальный шаг — конфигурация и инстанцирование объекта игры Phaser.Game. В конфиге указаны основные параметры: тип рендерера, размеры холста, цвет фона, родительский HTML-элемент и наша сцена Example.

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

const game = new Phaser.Game(config);

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

Easing-функция Bounce — это простой, но мощный инструмент для добавления физической убедительности и игривости в анимацию вашего проекта. Поэкспериментируйте, применяя эти твины не только к позиции (`x,y), но и к масштабу (scale), вращению (angle) или прозрачности (alpha) объектов. Попробуйте комбинировать разные easing-функции для разных свойств одного объекта или создайте цепочку твинов с помощьюtweens.chain()`, чтобы строить более сложные анимационные последовательности.