О чем этот пример
Работа с видео в играх — мощный инструмент для создания атмосферных кат-сцен, фонов и спецэффектов. Однако у видео есть состояние: оно может проигрываться, быть на паузе или завершиться. В примере bugs/4910 показана распространённая проблема: как корректно отслеживать состояние видео (в частности, паузу) для синхронизации игровой логики. Эта статья разберёт код примера, покажет, как загружать и управлять несколькими видео одновременно, и объяснит, почему мониторинг свойств вроде `video.paused` критически важен для сложных сцен.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: {
preload: preload,
create: create,
update: update
}
};
var vid1, vid2, vid3, vid4;
var debug1, debug2, debug3, debug4;
var game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
// this.load.video('wormhole', 'assets/video/wormhole.mp4');
// this.load.video('skull', 'assets/video/skull.mp4');
// this.load.video('underwater', 'assets/video/underwater.mp4');
// this.load.video('pumpkins', 'assets/video/pumpkins.mp4');
// this.load.video('mountains', 'assets/video/mountains.mp4');
// this.load.video('fireworks', 'assets/video/fireworks.mp4');
this.load.setCORS('anonymous');
this.load.setBaseURL('https://labs.phaser.io');
this.load.video('wormhole', 'assets/video/wormhole.mp4', 'canplaythrough', false);
this.load.video('skull', 'assets/video/skull.mp4', 'canplaythrough', false);
this.load.video('underwater', 'assets/video/underwater.mp4', 'canplaythrough', false);
this.load.video('pumpkins', 'assets/video/pumpkins.mp4', 'canplaythrough', false);
this.load.video('mountains', 'assets/video/mountains.mp4', 'canplaythrough', false);
this.load.video('fireworks', 'assets/video/fireworks.mp4', 'canplaythrough', false);
this.load.video('fireworks2', 'assets/video/fireworks.mp4', 'canplaythrough', false);
this.load.video('fireworks3', 'assets/video/fireworks.mp4', 'canplaythrough', false);
this.load.video('fireworks4', 'assets/video/fireworks.mp4', 'canplaythrough', false);
}
function create ()
{
vid1 = this.add.video(0, 0, 'wormhole').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid2 = this.add.video(400, 0, 'skull').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid3 = this.add.video(0, 300, 'mountains').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid4 = this.add.video(400, 300, 'pumpkins').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid1.play(true);
vid2.play(true);
vid3.play(true);
vid4.play(true);
window.v1 = vid1;
window.v2 = vid2;
window.v3 = vid3;
window.v4 = vid4;
debug1 = this.add.text(10, 10);
debug2 = this.add.text(10, 100);
debug3 = this.add.text(10, 200);
debug4 = this.add.text(10, 300);
}
function update ()
{
debug1.setText([
vid1.video.paused
]);
debug2.setText([
vid2.video.paused
]);
debug3.setText([
vid3.video.paused
]);
debug4.setText([
vid4.video.paused
]);
}
Настройка сцены и загрузка видео
Основная конфигурация игры стандартна: задаём размеры, цвет фона и привязываем три ключевые функции жизненного цикла сцены: preload, create и update.
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
В функции preload происходит загрузка видеофайлов. Обратите внимание на несколько важных деталей. Сначала базовый URL меняется на labs.phaser.io, и устанавливается CORS для корректной загрузки с другого домена. Метод this.load.video принимает несколько параметров: ключ ассета, путь к файлу, событие готовности ('canplaythrough') и флаг false, который указывает, что видео не должно создаваться как элемент VideoTexture (это полезно для экономии памяти при множественном использовании одного файла). В примере загружаются несколько уникальных видео и одно (fireworks) используется несколько раз под разными ключами.
function preload ()
{
this.load.setCORS('anonymous');
this.load.setBaseURL('https://labs.phaser.io');
this.load.video('wormhole', 'assets/video/wormhole.mp4', 'canplaythrough', false);
this.load.video('skull', 'assets/video/skull.mp4', 'canplaythrough', false);
// ... другие видео
this.load.video('fireworks4', 'assets/video/fireworks.mp4', 'canplaythrough', false);
}
Создание и запуск видеообъектов
В функции create создаются четыре видеообъекта с помощью this.add.video. Каждому задаётся позиция, масштаб 0.5, точка начала трансформации в левый верхний угол (setOrigin(0)) и низкая прозрачность (setAlpha(0.1)), чтобы можно было видеть несколько слоёв одновременно. Сразу после создания видео запускаются в бесконечный цикл с помощью play(true).
function create ()
{
vid1 = this.add.video(0, 0, 'wormhole').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid2 = this.add.video(400, 0, 'skull').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid3 = this.add.video(0, 300, 'mountains').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid4 = this.add.video(400, 300, 'pumpkins').setScale(0.5).setOrigin(0).setAlpha(0.1);
vid1.play(true);
vid2.play(true);
vid3.play(true);
vid4.play(true);
}
Также создаются четыре текстовых объекта debug1-debug4 для отображения отладочной информации. Они позиционируются по вертикали с шагом в 100 пикселей. Важный момент: видеообъекты присваиваются глобальным переменным window.v1-v4. Это сделано для удобства отладки в консоли браузера, чтобы можно было вручную проверять свойства видео.
Мониторинг состояния видео в реальном времени
Сердце примера — функция update, которая выполняется каждый кадр. Её задача — отслеживать и отображать состояние каждого видео. Ключевое свойство, которое проверяется, — vid1.video.paused. Оно возвращает true, если видео находится на паузе, и false, если проигрывается.
function update ()
{
debug1.setText([
vid1.video.paused
]);
debug2.setText([
vid2.video.paused
]);
debug3.setText([
vid3.video.paused
]);
debug4.setText([
vid4.video.paused
]);
}
Здесь vid1.video — это ссылка на нативный HTMLVideoElement, которым управляет Phaser. Мониторинг этого свойства в реальном времени позволяет реагировать на события, например, когда видео завершает воспроизведение (в данном примере цикл бесконечный, но в реальном сценарии после завершения видео может быть поставлено на паузу). Это особенно полезно для синхронизации кат-сцен с игровыми событиями или для переключения между несколькими видео.
Практическое применение: от отладки до игровой логики
Изначально этот пример был создан для отладки проблемы (bug #4910), связанной с корректным определением состояния видео. Однако принцип мониторинга video.paused имеет прямые практические применения.
Например, вы можете создать сцену с вступительным роликом и автоматически начать игру после его завершения:
function update() {
if (introVideo.video.paused && introVideo.video.currentTime >= introVideo.video.duration) {
// Видео завершилось и стоит на паузе
this.scene.start('Level1');
}
}
Или управлять фоновыми видео-слоями в зависимости от действий игрока. Например, при приближении к определённой области включать второе видео поверх основного, отслеживая, когда его можно безопасно остановить.
Важно помнить, что доступ к нативному элементу через .video даёт вам полный контроль, но также требует понимания HTML5 Video API.
Что попробовать дальше
Пример bugs/4910 наглядно демонстрирует важность отслеживания внутреннего состояния видеоэлементов в Phaser. Используя свойство .video.paused в цикле update, вы можете строить сложную логику, зависящую от завершения или паузы в видео. Для экспериментов попробуйте
- Изменить логику с бесконечного цикла на однократное воспроизведение и запускать новое видео по завершении предыдущего
- Связать паузу видео с паузой в игровом процессе (состояние
game.paused) - Создать интерфейс с кнопками, которые ставят конкретное видео на паузу или меняют его прозрачность, основываясь на данных из
update
