О чем этот пример
Работа с временными событиями — одна из ключевых задач в разработке игр. Вам может понадобиться запустить анимацию через несколько секунд после начала уровня, организовать появление врагов волнами или воспроизвести звуковые эффекты с задержкой. Встроенный в Phaser класс Timeline позволяет легко создавать и управлять таймлайнами событий, делая код чище и предсказуемее. В этой статье мы разберем, как работает Timeline на практическом примере, научимся добавлять события в определенные моменты времени и управлять их выполнением. Этот инструмент особенно полезен для скриптовых сцен, кат-сцен и любых игровых механик, требующих точного временного контроля.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const timeline = this.add.timeline();
for (let i = 0; i < 50; i++)
{
timeline.add({
at: i * 20,
once: true, // comment out to get to fin
run: () => console.log(i * 20)
});
}
// timeline.add({
// at: 1000,
// run: () => console.log('fin')
// });
timeline.play();
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d66',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Timeline и как его создать
Timeline — это встроенный в Phaser менеджер временных событий. Он позволяет планировать выполнение функций в определенные моменты времени относительно начала его воспроизведения.
Создается таймлайн через фабрику this.add.timeline(). Это метод сцены, который возвращает новый экземпляр класса Timeline.
const timeline = this.add.timeline();
После создания таймлайн находится в состоянии ожидания. Чтобы запустить отсчет времени и выполнение запланированных событий, необходимо явно вызвать метод .play().
Добавление событий: параметр `at` и функция `run`
Событие в таймлайн добавляется методом .add(). Он принимает объект конфигурации. Два ключевых свойства этого объекта:
- at: Время в миллисекундах от начала воспроизведения таймлайна, когда должно сработать событие.
- run: Функция-колбэк, которая будет выполнена в указанный момент времени.
В примере из исходного кода в цикле создается 50 событий. Каждое следующее событие запланировано на 20 мс позже предыдущего.
for (let i = 0; i < 50; i++)
{
timeline.add({
at: i * 20,
once: true,
run: () => console.log(i * 20)
});
}
Таким образом, первое событие сработает в момент 0 мс, второе — в 20 мс, третье — в 40 мс и так далее. В консоль будет выведено соответствующее время события.
Управление жизненным циклом событий: флаг `once`
В конфигурации события есть важное необязательное свойство once. Оно определяет, должно ли событие быть удалено из таймлайна после своего единственного выполнения.
timeline.add({
at: i * 20,
once: true, // Событие удалится после запуска
run: () => console.log(i * 20)
});
Если свойство once установлено в true (как в нашем примере), событие выполнится один раз в момент времени at и затем будет автоматически удалено из внутреннего списка таймлайна. Это предотвращает повторное выполнение, если таймлайн будет перезапущен.
Если закомментировать строку с once: true, событие останется в таймлайне. В текущем примере это не приведет к видимому эффекту, так как таймлайн проигрывается один раз. Однако если бы у нас был механизм перезапуска таймлайна (например, по нажатию клавиши), то все события без флага once выполнились бы снова.
Запуск таймлайна и логика выполнения
После того как все события добавлены, необходимо запустить таймлайн. Делается это методом .play().
timeline.play();
С этого момента начинается отсчет времени. Внутренний механизм Timeline проверяет, наступило ли время для выполнения какого-либо из запланированных событий. Когда системное время с момента вызова .play() достигает или превышает значение at для события, вызывается его функция run.
Важно понимать, что проверка происходит в рамках основного игрового цикла Phaser. Это обеспечивает стабильную работу и привязку к игровому времени, а не к реальному системному времени, что может быть важно при паузе или изменении скорости игры (timeScale).
Что попробовать дальше
Класс Timeline в Phaser — это мощный и простой инструмент для организации событий во времени. Он избавляет от необходимости вручную управлять таймерами и задержками, делая код для скриптовых последовательностей наглядным и линейным.
**Идеи для экспериментов:**
1. Создайте таймлайн для кат-сцены: в момент 0мс выведите текст, в 2000мс — измените выражение лица персонажа, в 4000мс — воспроизведите звук, в 6000мс — перейдите к следующей сцене.
2. Используйте таймлайн для спавна врагов волнами, где каждая волна — это событие с набором действий по созданию мобов.
3. Скомбинируйте таймлайн с анимациями. Запланируйте запуск анимации объекта (sprite.play()) или твина через определенные интервалы.
4. Поэкспериментируйте с флагом once: false, создайте циклический таймлайн и реализуйте его перезапуск по какому-либо игровому событию.
