О чем этот пример
Создание плавных и выразительных анимаций — ключ к оживлению игрового мира. В 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, чтобы создать движение "туда-обратно-пауза".
