О чем этот пример
Включение видеороликов может значительно обогатить игровой опыт, будь то кат-сцены, фоновые заставки или динамические текстуры. Однако современные браузеры строго регулируют автовоспроизведение видео со звуком, что может привести к неожиданным ошибкам. В этой статье мы разберём пример из официальной документации Phaser, который демонстрирует не только базовую загрузку и воспроизведение видео, но и правильную обработку блокировок браузера, а также реализацию интерактивного управления (пауза/продолжение) с помощью клика мыши. Вы научитесь создавать надёжный видеоплеер, готовый к реалиям веб-разработки.
Версия 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.video('spaceace', 'assets/video/spaceace.mp4');
}
create ()
{
const intro = this.add.video(640, 360, 'spaceace');
// Depending on browser settings video playback is locked
// from autoplaying because this video has audio.
// Catch the event here. Playback will start
// as soon as you click on the game (regardless if you have a
// click handler or not). Here we use it to display a message.
intro.on('locked', () => {
let message = this.add.text(640, 100, 'Click to play video', { font: '32px Courier', fill: '#00ff00' }).setShadow(1, 1).setOrigin(0.5);
intro.on('unlocked', () => {
message.destroy();
});
});
intro.play();
// Listen for the 'play' event to create our pause/resume handler
intro.once('play', () => {
this.input.on('pointerdown', () => {
if (intro.isPlaying())
{
intro.pause();
}
else
{
intro.resume();
}
});
});
}
}
const config = {
type: Phaser.AUTO,
width: 1280,
height: 720,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
let game = new Phaser.Game(config);
Загрузка видеоресурса
Как и любой другой ресурс, видео необходимо предзагрузить в методе preload(). Для этого используется метод this.load.video(). Первый аргумент — это уникальный ключ ассета, который будет использоваться для его создания в сцене. Второй аргумент — путь к файлу.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.video('spaceace', 'assets/video/spaceace.mp4');
}
В примере сначала задаётся базовый URL для загрузчиков сцены с помощью this.load.setBaseURL(). Это позволяет указывать относительные пути для всех последующих загрузок, что удобно для организации ресурсов.
Создание видеообъекта и проблема блокировки
Создать видеообъект на сцене так же просто, как и спрайт, с помощью метода this.add.video(). Ему передаются координаты (X, Y) и ключ загруженного видео.
const intro = this.add.video(640, 360, 'spaceace');
intro.play();
Однако вызов intro.play() может не сработать мгновенно. Браузеры блокируют автовоспроизведение видео, если у них есть звуковая дорожка, пока пользователь не взаимодействовал со страницей. В Phaser это состояние называется 'locked' (заблокировано). Чтобы корректно обработать эту ситуацию, нужно подписаться на событие 'locked' объекта видео.
intro.on('locked', () => {
let message = this.add.text(640, 100, 'Click to play video', { font: '32px Courier', fill: '#00ff00' }).setShadow(1, 1).setOrigin(0.5);
intro.on('unlocked', () => {
message.destroy();
});
});
В обработчике 'locked' мы создаём текстовое сообщение, информирующее пользователя о необходимости клика. Как только пользователь взаимодействует со страницей и блокировка снимается, срабатывает событие 'unlocked', и сообщение уничтожается методом .destroy().
Интерактивное управление воспроизведением
После того как видео начало воспроизводиться (событие 'play'), мы можем добавить более сложную логику управления. В примере по клику мыши видео ставится на паузу или возобновляется.
intro.once('play', () => {
this.input.on('pointerdown', () => {
if (intro.isPlaying())
{
intro.pause();
}
else
{
intro.resume();
}
});
});
Обратите внимание на несколько ключевых моментов:
1. Используется intro.once('play', ...), чтобы подписаться на событие первого запуска видео только один раз и не дублировать обработчики.
2. Внутри этого события на глобальный клик (this.input.on('pointerdown', ...)) вешается обработчик.
3. Метод intro.isPlaying() возвращает true, если видео в данный момент проигрывается, и false, если оно на паузе или остановлено.
4. В зависимости от состояния, вызываются методы .pause() или .resume().
Конфигурация игры и запуск сцены
Код завершается стандартной для Phaser конфигурацией игры и её инстанцированием. Важно убедиться, что размеры сцены (width, height) соответствуют ожидаемому разрешению видео и координатам размещения элементов интерфейса (например, текстового сообщения).
const config = {
type: Phaser.AUTO,
width: 1280,
height: 720,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
let game = new Phaser.Game(config);
Здесь создаётся игровой экран размером 1280x720 пикселей с чёрным фоном. Класс нашей сцены Example передаётся в свойство scene конфигурации.
Что попробовать дальше
Работа с видео в Phaser требует учёта не только игрового API, но и ограничений веб-платформы. Основной паттерн: загрузить, создать, попытаться воспроизвести и обязательно обработать возможную блокировку. После успешного старта вы получаете полный контроль над плеером. Для экспериментов попробуйте: зациклить видео с помощью intro.setLoop(true); использовать видео в качестве текстуры для Sprite или Plane; добавить управление громкостью через intro.setVolume(); или реализовать перемотку, изменяя свойство intro.currentTime.
