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

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

Версия 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/skies/space3.png');
        this.load.video('astronaut', 'assets/video/astronaut.webm', true);
    }

    create ()
    {
        this.add.image(400, 300, 'bg');

        const intro = this.add.video(400, 300, 'astronaut');

        intro.on('locked', () => {

            let message = this.add.text(400, 100, 'Click to play video', { font: '32px Courier', fill: '#00ff00' }).setShadow(1, 1).setOrigin(0.5);

            intro.on('unlocked', () => {

                message.destroy();

            });

        });

        let loops = 0;
        let counter = this.add.text(400, 550, 'Loops: 0', { font: '32px Courier', fill: '#ffffff' }).setOrigin(0.5);

        intro.on('loop', () => {

            loops++;

            counter.setText('Loops: ' + loops);

        });

        intro.play(true);
    }
}

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

let game = new Phaser.Game(config);

Загрузка видеоресурсов

Перед использованием видео, как и любой другой ассет, его необходимо загрузить. В методе preload() мы указываем базовый URL и загружаем изображение фона и видеофайл.

Ключевой момент — третий параметр в load.video(). Установка его в true означает, что видео загрузится с поддержкой кросс-ориджина (CORS), что необходимо для его корректного воспроизведения на многих веб-хостах.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('bg', 'assets/skies/space3.png');
    this.load.video('astronaut', 'assets/video/astronaut.webm', true);
}

Создание и базовое управление видеообъектом

В методе create() мы сначала добавляем фоновое изображение, а затем создаем видеообъект (Video Game Object). Он создается с помощью this.add.video(), где первые два аргумента — координаты X и Y для центра видео.

Метод play(true) запускает воспроизведение. Передача true в качестве аргумента включает автоматическое зацикливание видео: когда клип закончится, он начнется заново.

create ()
{
    this.add.image(400, 300, 'bg');
    const intro = this.add.video(400, 300, 'astronaut');
    intro.play(true);
}

Обработка событий: loop и пользовательский ввод

Phaser позволяет реагировать на события видеообъекта. В примере показана работа с двумя событиями: 'loop' и 'locked'.

Событие 'loop' генерируется каждый раз, когда видео завершает один цикл воспроизведения и начинает следующий. Мы используем его для подсчета и отображения количества повторов.

let loops = 0;
let counter = this.add.text(400, 550, 'Loops: 0', { font: '32px Courier', fill: '#ffffff' }).setOrigin(0.5);

intro.on('loop', () => {
    loops++;
    counter.setText('Loops: ' + loops);
});

События 'locked' и 'unlocked' связаны с политикой автовоспроизведения в браузерах. Видео не может начать играть автоматически без жеста пользователя. Событие 'locked' срабатывает, если видео заблокировано. Мы показываем подсказку, которую уничтожаем (destroy()) при разблокировке ('unlocked').

intro.on('locked', () => {
    let message = this.add.text(400, 100, 'Click to play video', { font: '32px Courier', fill: '#00ff00' }).setShadow(1, 1).setOrigin(0.5);
    intro.on('unlocked', () => {
        message.destroy();
    });
});

Конфигурация игры

Код завершается стандартной конфигурацией игры Phaser. Важно убедиться, что width и height конфига достаточно велики для отображения вашего видео. В данном примере видео помещается в центр холста размером 800x600.

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

let game = new Phaser.Game(config);

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

Использование зацикленного видео открывает простой путь к добавлению «живых» элементов в вашу игру на Phaser 3. Вы можете использовать этот подход для создания пламенных костров, мерцающих голограмм, текущей воды или, как в примере, эффекта невесомости. Для экспериментов попробуйте

  1. Связать событие 'loop' с изменением других параметров игры (например, скорости вращения спрайта)
  2. Наложить несколько полупрозрачных видео друг на друга для создания сложных эффектов
  3. Использовать intro.setLoop(true) для динамического включения/выключения зацикливания в ответ на действия игрока