Play and skip intro video (Phaser 3)

Hey guys,

I wrote a super simple scene plugin in order to play an intro before any gameplay.
For example a small logo animation. Users can skip the video with any configured keys (Default is ENTER or SPACE).

Maybe this code helps anyone.
I also created a gist with a more detailed description.

Just copy the plugin file, register it like any other scene plugin and add a video to your scene:

preload () {
    this.load.video('nhb_intro', 'assets/videos/nhb_intro.mp4', 'loadeddata', false, false)
}
    
async create () {
    // Use default settings (Skip via ENTER or SPACE)
    await this.introManager.playIntro('nhb_intro')

    // Start any scene after intro video finished
    this.scene.start('myStartScene')
}

Here’s the plugin code:

import Phaser from 'phaser'

export default class NhbIntroPlugin extends Phaser.Plugins.ScenePlugin {
    constructor (scene, pluginManager) {
        super(scene, pluginManager)

        this.defaultConfig = {
            skipKeys: ['ENTER', 'SPACE'],
        }

        this.intro = null
        this.keyObjects = []
    }

    /**
     * @param {string} videoId
     * @param {object} config
     *
     * @returns {Promise<unknown>}
     */
    playIntro (videoId, config = {}) {
        // Overwrite config
        if (!config) {
            config = this.defaultConfig
        }

        return new Promise((resolve) => {
            this.intro = this.scene.add.video(0, 0, videoId)

            // Center video in canvas
            this.intro.setOrigin(0, 0)
            this.intro.setPosition(
                (this.game.canvas.width / 2) - (this.intro.width / 2),
                (this.game.canvas.height / 2) - (this.intro.height / 2),
            )

            // Start video once the audio context was triggered
            this.scene.sound.once(Phaser.Sound.Events.UNLOCKED, () => {
                this.intro.play(false)
                this.intro.setPaused(false)
            })

            // Check when to skip the video
            config.skipKeys.forEach((key, i) => {
                this.keyObjects[i] = this.scene.input.keyboard.addKey(key)
                this.keyObjects[i].once('down', () => {
                    // Skip video
                    this.intro.setPaused(true)
                    this.reset()
                    resolve()
                })
            })

            this.intro.once('complete', () => {
                resolve()
            })
        })
    }

    /**
     * Stop video and remove all listeners
     */
    reset () {
        this.intro.setPaused(true)
        this.intro.off('complete')
        this.intro = null

        this.keyObjects.forEach(keyObject => {
            keyObject.off('down')
        })
        this.keyObjects = []
    }
}

Best regards
Nick