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

Создание плавных и выразительных анимаций — ключ к оживлению игрового мира. В Phaser 3 система tween предлагает мощные инструменты для управления движением объектов. Одним из таких инструментов является параметр `loopDelay`, который позволяет вставлять паузы между повторениями циклической анимации. Эта статья будет полезна, если вы хотите создать анимацию с "дыханием", периодическим миганием объекта или любое другое движение, где между циклами нужна преднамеренная задержка. Мы разберем практический пример, который покажет, как заставить спрайт двигаться туда-обратно, делая паузу в начальной точке.

Версия 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 marker = this.add.image(100, 300, 'block').setAlpha(0.3);
        var image = this.add.image(100, 300, 'block');

        this.tweens.add({
            targets: image,
            x: 700,
            duration: 2000,
            ease: 'Sine.easeInOut',
            loop: -1,
            loopDelay: 2000
        });
    }
}

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

const game = new Phaser.Game(config);

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

При создании циклической анимации с помощью tweens.add() и параметра loop: -1, анимация повторяется бесконечно без перерыва. Это не всегда желательно. Например, представьте врага, который патрулирует платформу: он доходит до края, мгновенно разворачивается и идет обратно. Чтобы добавить реалистичности или просто визуальный интерес, можно сделать так, чтобы враг на краю платформы немного "постоял", осмотрелся.

Именно для этого и существует параметр loopDelay. Он задает задержку в миллисекундах, которая будет происходить **перед началом каждого нового цикла** анимации, после того как предыдущий цикл полностью завершится.

loopDelay: 2000 // Пауза в 2 секунды перед каждым новым циклом

Разбор примера: спрайт с паузой

Рассмотрим исходный код примера. В нем создается простая сцена, которая загружает один спрайт и применяет к нему tween.

Сначала в методе preload() загружается текстура блока.

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

В методе create() мы создаем два спрайта с одной текстурой. Первый, marker, служит полупрозрачной меткой, отмечающей начальную позицию анимации. Второй, image, — это тот спрайт, который мы будем анимировать.

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

Создание tween с задержкой цикла

Самая важная часть — создание и конфигурация tween-анимации. Мы передаем объект с настройками в метод this.tweens.add().

this.tweens.add({
    targets: image, // Объект для анимации
    x: 700,        // Конечная координата X
    duration: 2000, // Длительность одного цикла (2 секунды)
    ease: 'Sine.easeInOut', // Плавная функция easing
    loop: -1,       // Бесконечный цикл
    loopDelay: 2000 // Задержка 2 секунды перед каждым циклом
});

Давайте пошагово представим жизненный цикл этой анимации: 1. **Старт:** Спрайт image начинает движение от X=100 до X=700. Длится это 2 секунды (duration). 2. **Конец первого цикла:** Спрайт достигает точки X=700. 3. **Пауза (loopDelay):** Происходит ничего. Спрайт 2 секунды просто стоит на месте X=700. 4. **Начало второго цикла:** Tween сбрасывается. Спрайт мгновенно возвращается в начальную позицию X=100 (это стандартное поведение tween в Phaser) и снова начинает 2-секундное движение к X=700. 5. **Повтор:** Шаги 2-4 повторяются бесконечно из-за loop: -1.

Ключевой момент: задержка происходит именно в **конечной точке** анимации (X=700), потому что tween завершает свой цикл, а затем ждет loopDelay миллисекунд, прежде чем начать следующий.

Практическое применение и вариации

Параметр loopDelay открывает путь к более сложным и "живым" анимациям без написания дополнительной логики состояний.

**Примеры использования:** * **Патрулирование:** Враг идет от точки A к B, стоит (задержка), затем идет обратно. * "**Дыхание" объекта:** Пульсация масштаба (scaleX, scaleY) с паузой в максимальном или минимальном размере. * **Мигание с интервалом:** Изменение alpha от 1 до 0 и обратно, но с паузой в видимом или невидимом состоянии. * **Ожидание перед атакой:** Анимация "заряда" (например, накопление энергии в спрайте) с паузой перед "выстрелом" (следующим циклом).

**Эксперимент 1: Пауза в начале цикла.** В текущем примере пауза в конце. Чтобы сделать паузу в начале (в точке X=100), нужно настроить tween на движение от X=700 к X=100. Просто поменяйте начальную позицию спрайта image и значение свойства `x` в конфиге tween.

create() {
    // Метка теперь на конечной позиции
    var marker = this.add.image(700, 300, 'block').setAlpha(0.3);
    // Спрайт начинает с конечной позиции
    var image = this.add.image(700, 300, 'block');

    this.tweens.add({
        targets: image,
        x: 100, // Двигаемся теперь к 100
        duration: 2000,
        ease: 'Sine.easeInOut',
        loop: -1,
        loopDelay: 2000 // Пауза будет в точке X=100
    });
}

**Эксперимент 2: Разные задержки.** Значение loopDelay может быть любым числом. Попробуйте 500 для короткой паузы или 5000 для очень долгой.

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

Параметр loopDelay в системе tween Phaser 3 — это простой, но мощный способ добавить ритм и выразительность циклическим анимациям. Он позволяет создавать более сложные паттерны движения, имитирующие поведение, без необходимости разбивать анимацию на несколько отдельных твинов или управлять таймерами вручную. Для дальнейших экспериментов попробуйте: 1. Скомбинировать loopDelay с delay (задержка перед самым первым стартом анимации). 2. Создать два встречных спрайта с tween, у которых loopDelay настроен так, чтобы они "передавали эстафету", стартуя по очереди. 3. Использовать yoyo: true вместе с loop и loopDelay, чтобы создать движение "туда-обратно-пауза".