Build games as easily as you play them — join the Phaser Beam waitlist for Early Access.
                
            
            export default class Boot extends Phaser.Scene { constructor () { super('Boot'); } preload () { this.load.setBaseURL('https://cdn.phaserfiles.com/v355'); this.load.image('loading', 'assets/games/bank-panic/loading.png'); } create () { this.scene.start('Preloader'); } }
export default class MainMenu extends Phaser.Scene { constructor () { super('MainMenu'); } create () { this.add.image(512, 384, 'title'); let sign = this.add.image(512, -400, 'logo'); this.tweens.add({ targets: sign, y: 180, ease: 'Bounce.easeOut', duration: 2000 }); let cactus1 = this.add.image(150, 680, 'https://labs.phaser.io/assets', 'cactus'); let cactus2 = this.add.image(880, 680, 'https://labs.phaser.io/assets', 'cactus').setFlipX(true); this.tweens.add({ targets: cactus1, props: { scaleX: { value: 0.9, duration: 250 }, scaleY: { value: 1.1, duration: 250 }, angle: { value: -20, duration: 500, delay: 250 }, y: { value: 660, duration: 250 } }, ease: 'Sine.easeInOut', repeat: -1, yoyo: true }); this.tweens.add({ targets: cactus2, props: { scaleX: { value: 0.9, duration: 250 }, scaleY: { value: 1.1, duration: 250 }, angle: { value: 20, duration: 500, delay: 250 }, y: { value: 660, duration: 250 } }, ease: 'Sine.easeInOut', repeat: -1, yoyo: true }); this.music = this.sound.play('music', { loop: true }); this.input.once('pointerdown', () => { this.sound.stopAll(); this.sound.play('shot'); this.scene.start('MainGame'); }); } }
export default class Preloader extends Phaser.Scene { constructor () { super('Preloader'); } preload () { this.load.setBaseURL('https://cdn.phaserfiles.com/v355'); this.loading = this.add.image(512, 384, 'loading'); this.load.setPath('assets/games/bank-panic/'); this.load.image('start'); this.load.image('title'); this.load.image('logo'); this.load.image('background'); this.load.image('bulletHole', 'bullet-hole.png'); this.load.atlas('https://labs.phaser.io/assets', 'bank-panic.png', 'bank-panic.json'); this.load.audio('shot', [ 'shot.ogg', 'shot.m4a', 'shot.mp3' ]); this.load.audio('banditShot', [ '50cal.ogg', '50cal.m4a', '50cal.mp3' ]); this.load.audio('money', [ 'money.ogg', 'money.m4a', 'money.mp3' ]); this.load.audio('levelComplete', [ 'complete.ogg', 'complete.m4a', 'complete.mp3' ]); this.load.audio('gameOver', [ 'gameover.ogg', 'gameover.m4a', 'gameover.mp3' ]); this.load.audio('music', [ 'music.ogg', 'music.m4a', 'music.mp3' ]); this.load.audio('door', [ 'door.ogg', 'door.m4a', 'door.mp3' ]); this.load.audio('scream1', [ 'scream1.ogg', 'scream1.m4a', 'scream1.mp3' ]); this.load.audio('scream2', [ 'scream2.ogg', 'scream2.m4a', 'scream2.mp3' ]); this.load.audio('scream3', [ 'scream3.ogg', 'scream3.m4a', 'scream3.mp3' ]); } create () { // Create our global animations this.anims.create({ key: 'doorOpen', frames: this.anims.generateFrameNames('https://labs.phaser.io/assets', { prefix: 'door', start: 1, end: 5 }), frameRate: 20 }); this.anims.create({ key: 'doorClose', frames: this.anims.generateFrameNames('https://labs.phaser.io/assets', { prefix: 'door', start: 5, end: 1 }), frameRate: 20 }); this.loading.setTexture('start'); this.loading.setInteractive(); this.loading.once('pointerdown', () => { this.scene.start('MainMenu'); }); } }
import Door from './Door.js'; export default class MainGame extends Phaser.Scene { constructor () { super('MainGame'); this.hats; this.goals; this.gold; this.doors; this.isPaused = false; this.goalsComplete = 0; this.sign; this.level = 1; this.levelImage; this.killDelay = 0.7; this.closeDurationLow = 2000; this.closeDurationHigh = 4000; } create () { this.add.image(512, 384, 'background'); // Level text this.add.image(450, 650, 'https://labs.phaser.io/assets', 'levelText'); this.levelImage = this.add.image(600, 650, 'https://labs.phaser.io/assets', '1'); this.createGoals(); this.createDoors(); this.hats = this.add.group({ defaultKey: 'https://labs.phaser.io/assets', defaultFrame: 'hat', key: 'https://labs.phaser.io/assets', frame: 'hat', active: false, visible: false, repeat: 32, maxSize: 32 }); this.gold = this.add.group({ defaultKey: 'https://labs.phaser.io/assets', defaultFrame: 'gold', key: 'https://labs.phaser.io/assets', frame: 'gold', active: false, visible: false, repeat: 11, maxSize: 12 }); this.isPaused = false; this.level = 1; this.killDelay = 0.8; this.closeDurationLow = 2000; this.closeDurationHigh = 4000; this.doors.forEach((door) => { door.start(this.game.getTime()); }); } createGoals () { this.goals = []; this.goalsComplete = 0; for (let i = 1; i <= 12; i++) { this.goals.push(this.add.image(0, 0, 'https://labs.phaser.io/assets', i)); } Phaser.Actions.GridAlign(this.goals, { width: 12, height: 1, cellWidth: 80, cellHeight: 36, x: 80, y: 86 }); } createDoors () { this.doors = []; let doorWidth = 200; let doorSpace = Math.floor((1024 - (doorWidth * 4)) / 5); let x = 100 + doorSpace; let y = 352; for (let i = 1; i <= 4; i++) { this.doors.push(new Door('Door' + i, this, x, y)) x += doorWidth + doorSpace; } } addGold (x, y) { let target = this.goals[this.goalsComplete]; let gold = this.gold.get(x + 50, y + 100); gold.setActive(true).setVisible(true); this.sound.play('money'); this.tweens.add({ targets: gold, x: target.x, y: target.y, duration: 600, ease: 'Quad.easeOut', onComplete: () => { target.setVisible(false); } }); this.goalsComplete++; if (this.goalsComplete === 12) { this.levelComplete(); } } addHat (x, y, stackPosition) { y = 180 + (30 * (5 - stackPosition)); let hat = this.hats.get(x, y); hat.setActive(true).setVisible(true); hat.setScale(1).setAlpha(1); const destX = Phaser.Math.RND.between(x - 400, x + 400); const destY = y - 400; this.tweens.add({ targets: hat, x: destX, y: destY, angle: 960, duration: 1000, ease: 'Quad.easeOut', onComplete: () => { hat.setActive(false); hat.setVisible(false); } }); } levelFail () { this.isPaused = true; this.sign = this.add.image(512, -200, 'https://labs.phaser.io/assets', 'gameOver'); this.sound.play('gameOver'); this.tweens.add({ targets: this.sign, y: 384, ease: 'Bounce.easeOut', duration: 1500, onComplete: () => { this.input.once('pointerdown', () => this.scene.start('MainMenu')); } }); } levelComplete () { this.isPaused = true; this.sign = this.add.image(512, -200, 'https://labs.phaser.io/assets', 'levelComplete'); this.sound.play('levelComplete'); this.tweens.add({ targets: this.sign, y: 384, ease: 'Bounce.easeOut', duration: 1500, onComplete: () => { this.input.once('pointerdown', () => this.nextLevel()); } }); } nextLevel () { this.goals.forEach((goal, index) => { goal.setFrame((index + 1).toString()); goal.setVisible(true); }); this.gold.getChildren().forEach((gold) => { gold.setVisible(false); gold.setActive(false); }); // Reset everything this.doors.forEach((door) => { door.reset(this.game.getTime()); }); this.goalsComplete = 0; // Change difficulty if (this.level < 5) { this.killDelay -= 0.1; } if (this.level < 10) { this.closeDurationLow -= 100; this.closeDurationHigh -= 200; } // Change level counter this.level++; this.levelImage.setFrame(this.level); this.sign.setVisible(false); this.isPaused = false; } killed (x, y) { // Bullet holes on the screen let offsetX = 100; for (let i = 0; i < 3; i++) { let x = Phaser.Math.RND.between(offsetX, offsetX + 200); let y = Phaser.Math.RND.between(200, 600); let hole = this.add.image(x, y, 'bulletHole').setAlpha(0); this.tweens.add({ targets: hole, alpha: 1, duration: 30, delay: 200 * i }); offsetX += 340; } this.levelFail(); } update (time) { if (!this.isPaused) { this.doors.forEach((door) => { door.update(time); }); } } }
import Boot from './Boot.js'; import Preloader from './Preloader.js'; import MainMenu from './MainMenu.js'; import MainGame from './Game.js'; const config = { type: Phaser.AUTO, width: 1024, height: 768, backgroundColor: '#2e91f3', parent: 'phaser-example', scene: [ Boot, Preloader, MainMenu, MainGame ] }; let game = new Phaser.Game(config);
export default class Door extends Phaser.GameObjects.Container { constructor (name, scene, x, y) { super(scene, x, y); this.name = name; this.background = scene.add.image(0, 0, 'https://labs.phaser.io/assets', 'doorBackground'); this.door = scene.add.sprite(0, 0, 'https://labs.phaser.io/assets', 'door1'); this.character = scene.add.image(0, 0, 'https://labs.phaser.io/assets', 'bandit1'); this.characterFrame = 'bandit1'; this.isOpen = false; this.isBandit = false; this.isHats = false; this.isDead = false; this.wasBandit = (scene.doors.length % 2) ? true : false; this.hats = 0; this.timeToOpen = Number.MAX_SAFE_INTEGER; this.timeToClose = Number.MAX_SAFE_INTEGER; this.timeToKill = 0; this.characters = [ 'bandit1', 'bandit2', 'cowboy1', 'cowboy2', 'hat' ]; this.add([ this.background, this.character, this.door ]); this.setSize(200, 400); this.setInteractive(); this.on('pointerup', this.shoot, this); scene.add.existing(this); } destroy () { this.off('pointerup'); } start (time) { this.timeToOpen = time + Phaser.Math.RND.between(500, 4000); } reset (time) { this.isOpen = false; this.isBandit = false; this.isHats = false; this.isDead = false; this.door.play('doorClose'); this.timeToOpen = time + Phaser.Math.RND.between(500, 4000); } openDoor (time) { this.isOpen = true; this.isBandit = false; this.isHats = false; this.isDead = false; this.characterFrame = Phaser.Utils.Array.GetRandom(this.characters); // When should this door close again? const duration = Phaser.Math.RND.between(this.scene.closeDurationLow, this.scene.closeDurationHigh); this.timeToClose = time + duration; if (this.characterFrame === 'bandit1' || this.characterFrame === 'bandit2') { this.isBandit = true; } else if (this.characterFrame === 'hat') { this.isHats = true; // Pick random number of hats this.hats = Phaser.Math.RND.between(2, 5); this.characterFrame += this.hats.toString(); } else { this.timeToClose = time + (duration / 2); } // If we had a citizen or hats on our last go, we have to have a bandit now if (!this.wasBandit && !this.isBandit) { this.isHats = false; this.hats = 0; this.isBandit = true; this.characterFrame = (Math.random() > 0.5) ? 'bandit1' : 'bandit2'; this.timeToClose = time + duration; } this.character.setFrame(this.characterFrame); this.character.setScale(1).setAlpha(1); if (this.isBandit) { this.timeToKill = time + (duration * this.scene.killDelay); } this.scene.sound.play('door'); this.door.play('doorOpen'); } closeDoor (time) { this.door.play('doorClose'); this.isOpen = false; this.wasBandit = this.isBandit; if (!this.isBandit && !this.isHats && !this.isDead) { this.scene.addGold(this.x, this.y); } // When should this door open again? this.timeToOpen = time + Phaser.Math.RND.between(2000, 4000); } shoot () { if (!this.isOpen || this.scene.isPaused) { return; } this.scene.sound.play('shot'); if (this.isDead) { // We will want to hear the gunshot, but not actually do anything with it return; } if (this.isBandit) { this.shootCharacter(true); } else { if (this.isHats) { this.shootHat(); } else { this.shootCharacter(false); } } } shootCharacter (closeDoor) { this.isDead = true; this.characterFrame += 'Dead'; this.character.setFrame(this.characterFrame); this.scene.sound.play('scream' + Phaser.Math.RND.between(1, 3)); this.scene.tweens.add({ targets: this.character, scaleX: 0.5, scaleY: 0.5, duration: 300, onComplete: () => { if (closeDoor) { this.closeDoor(this.scene.game.getTime()); } else { this.scene.levelFail(); } } }); // No more shots at this door if (!closeDoor) { this.off('pointerup'); this.scene.isPaused = true; } } shootHat () { if (this.hats > 0) { this.scene.addHat(this.x, this.y, this.hats); this.hats--; this.characterFrame = 'hat' + this.hats; } this.character.setFrame(this.characterFrame); } shootYou () { this.off('pointerup'); this.scene.isPaused = true; // Shots let shot1 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'shot1'); let shot2 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'shot2'); this.scene.sound.play('banditShot'); this.scene.sound.play('banditShot', { delay: 0.25 }); this.scene.sound.play('banditShot', { delay: 0.5 }); this.scene.tweens.add({ targets: shot1, alpha: 0, duration: 200, ease: 'Power2' }); this.scene.tweens.add({ targets: shot2, alpha: 0, duration: 200, delay: 200, ease: 'Power2', onComplete: () => { this.scene.killed(this.x, this.y); } }); // Gun smoke rising from the bandit let smoke1 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'smoke1'); let smoke2 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'smoke2'); this.scene.tweens.add({ targets: smoke1, props: { y: { value: 150, duration: 1000, ease: 'Sine.easeInOut' }, alpha: { value: 0, duration: 250, ease: 'Power2', delay: 750 } } }); this.scene.tweens.add({ targets: smoke2, props: { y: { value: 150, duration: 1000, ease: 'Sine.easeInOut', delay: 500 }, alpha: { value: 0, duration: 250, ease: 'Power2', delay: 1250 } } }); } update (time) { if (!this.isOpen && time >= this.timeToOpen) { this.openDoor(time); } else if (this.isOpen && time >= this.timeToClose) { this.closeDoor(time); } else if (this.isOpen && this.isBandit && !this.isDead && time >= this.timeToKill) { this.shootYou(); } } }
export default class Boot extends Phaser.Scene
{
    constructor ()
    {
        super('Boot');
    }
    preload ()
    {
        this.load.setBaseURL('https://cdn.phaserfiles.com/v355');
        this.load.image('loading', 'assets/games/bank-panic/loading.png');
    }
    create ()
    {
        this.scene.start('Preloader');
    }
}
            export default class MainMenu extends Phaser.Scene
{
    constructor ()
    {
        super('MainMenu');
    }
    create ()
    {
        this.add.image(512, 384, 'title');
        let sign = this.add.image(512, -400, 'logo');
        this.tweens.add({
            targets: sign,
            y: 180,
            ease: 'Bounce.easeOut',
            duration: 2000
        });
        let cactus1 = this.add.image(150, 680, 'https://labs.phaser.io/assets', 'cactus');
        let cactus2 = this.add.image(880, 680, 'https://labs.phaser.io/assets', 'cactus').setFlipX(true);
        this.tweens.add({
            targets: cactus1,
            props: {
                scaleX: { value: 0.9, duration: 250 },
                scaleY: { value: 1.1, duration: 250 },
                angle: { value: -20, duration: 500, delay: 250 },
                y: { value: 660, duration: 250 }
            },
            ease: 'Sine.easeInOut',
            repeat: -1,
            yoyo: true
        });
        this.tweens.add({
            targets: cactus2,
            props: {
                scaleX: { value: 0.9, duration: 250 },
                scaleY: { value: 1.1, duration: 250 },
                angle: { value: 20, duration: 500, delay: 250 },
                y: { value: 660, duration: 250 }
            },
            ease: 'Sine.easeInOut',
            repeat: -1,
            yoyo: true
        });
        this.music = this.sound.play('music', { loop: true });
        this.input.once('pointerdown', () => {
            this.sound.stopAll();
            this.sound.play('shot');
            this.scene.start('MainGame');
        });
    }
}
            export default class Preloader extends Phaser.Scene
{
    constructor ()
    {
        super('Preloader');
    }
    preload ()
    {
        this.load.setBaseURL('https://cdn.phaserfiles.com/v355');
        this.loading = this.add.image(512, 384, 'loading');
        this.load.setPath('assets/games/bank-panic/');
        this.load.image('start');
        this.load.image('title');
        this.load.image('logo');
        this.load.image('background');
        this.load.image('bulletHole', 'bullet-hole.png');
        this.load.atlas('https://labs.phaser.io/assets', 'bank-panic.png', 'bank-panic.json');
        this.load.audio('shot', [ 'shot.ogg', 'shot.m4a', 'shot.mp3' ]);
        this.load.audio('banditShot', [ '50cal.ogg', '50cal.m4a', '50cal.mp3' ]);
        this.load.audio('money', [ 'money.ogg', 'money.m4a', 'money.mp3' ]);
        this.load.audio('levelComplete', [ 'complete.ogg', 'complete.m4a', 'complete.mp3' ]);
        this.load.audio('gameOver', [ 'gameover.ogg', 'gameover.m4a', 'gameover.mp3' ]);
        this.load.audio('music', [ 'music.ogg', 'music.m4a', 'music.mp3' ]);
        this.load.audio('door', [ 'door.ogg', 'door.m4a', 'door.mp3' ]);
        this.load.audio('scream1', [ 'scream1.ogg', 'scream1.m4a', 'scream1.mp3' ]);
        this.load.audio('scream2', [ 'scream2.ogg', 'scream2.m4a', 'scream2.mp3' ]);
        this.load.audio('scream3', [ 'scream3.ogg', 'scream3.m4a', 'scream3.mp3' ]);
    }
    create ()
    {
        //  Create our global animations
        this.anims.create({
            key: 'doorOpen',
            frames: this.anims.generateFrameNames('https://labs.phaser.io/assets', { prefix: 'door', start: 1, end: 5 }),
            frameRate: 20
        });
        this.anims.create({
            key: 'doorClose',
            frames: this.anims.generateFrameNames('https://labs.phaser.io/assets', { prefix: 'door', start: 5, end: 1 }),
            frameRate: 20
        });
        this.loading.setTexture('start');
        this.loading.setInteractive();
        this.loading.once('pointerdown', () => {
            this.scene.start('MainMenu');
        });
    }
}
            import Door from './Door.js';
export default class MainGame extends Phaser.Scene
{
    constructor ()
    {
        super('MainGame');
        this.hats;
        this.goals;
        this.gold;
        this.doors;
        this.isPaused = false;
        this.goalsComplete = 0;
        this.sign;
        this.level = 1;
        this.levelImage;
        this.killDelay = 0.7;
        this.closeDurationLow = 2000;
        this.closeDurationHigh = 4000;
    }
    create ()
    {
        this.add.image(512, 384, 'background');
        //  Level text
        this.add.image(450, 650, 'https://labs.phaser.io/assets', 'levelText');
        this.levelImage = this.add.image(600, 650, 'https://labs.phaser.io/assets', '1');
        this.createGoals();
        this.createDoors();
        this.hats = this.add.group({
            defaultKey: 'https://labs.phaser.io/assets',
            defaultFrame: 'hat',
            key: 'https://labs.phaser.io/assets',
            frame: 'hat',
            active: false,
            visible: false,
            repeat: 32,
            maxSize: 32
        });
        this.gold = this.add.group({
            defaultKey: 'https://labs.phaser.io/assets',
            defaultFrame: 'gold',
            key: 'https://labs.phaser.io/assets',
            frame: 'gold',
            active: false,
            visible: false,
            repeat: 11,
            maxSize: 12
        });
        this.isPaused = false;
        this.level = 1;
        this.killDelay = 0.8;
        this.closeDurationLow = 2000;
        this.closeDurationHigh = 4000;
        this.doors.forEach((door) => {
            door.start(this.game.getTime());
        });
    }
    createGoals ()
    {
        this.goals = [];
        this.goalsComplete = 0;
        for (let i = 1; i <= 12; i++)
        {
            this.goals.push(this.add.image(0, 0, 'https://labs.phaser.io/assets', i));
        }
        Phaser.Actions.GridAlign(this.goals, {
            width: 12,
            height: 1,
            cellWidth: 80,
            cellHeight: 36,
            x: 80,
            y: 86
        });
    }
    createDoors ()
    {
        this.doors = [];
        let doorWidth = 200;
        let doorSpace = Math.floor((1024 - (doorWidth * 4)) / 5);
        let x = 100 + doorSpace;
        let y = 352;
        for (let i = 1; i <= 4; i++)
        {
            this.doors.push(new Door('Door' + i, this, x, y))
            x += doorWidth + doorSpace;
        }
    }
    addGold (x, y)
    {
        let target = this.goals[this.goalsComplete];
        let gold = this.gold.get(x + 50, y + 100);
        gold.setActive(true).setVisible(true);
        this.sound.play('money');
        this.tweens.add({
            targets: gold,
            x: target.x,
            y: target.y,
            duration: 600,
            ease: 'Quad.easeOut',
            onComplete: () => {
                target.setVisible(false);
            }
        });
        this.goalsComplete++;
        if (this.goalsComplete === 12)
        {
            this.levelComplete();
        }
    }
    addHat (x, y, stackPosition)
    {
        y = 180 + (30 * (5 - stackPosition));
        let hat = this.hats.get(x, y);
        hat.setActive(true).setVisible(true);
        hat.setScale(1).setAlpha(1);
        const destX = Phaser.Math.RND.between(x - 400, x + 400);
        const destY = y - 400;
        this.tweens.add({
            targets: hat,
            x: destX,
            y: destY,
            angle: 960,
            duration: 1000,
            ease: 'Quad.easeOut',
            onComplete: () => {
                hat.setActive(false);
                hat.setVisible(false);
            }
        });
    }
    levelFail ()
    {
        this.isPaused = true;
        this.sign = this.add.image(512, -200, 'https://labs.phaser.io/assets', 'gameOver');
        this.sound.play('gameOver');
        this.tweens.add({
            targets: this.sign,
            y: 384,
            ease: 'Bounce.easeOut',
            duration: 1500,
            onComplete: () => {
                this.input.once('pointerdown', () => this.scene.start('MainMenu'));
            }
        });
    }
    levelComplete ()
    {
        this.isPaused = true;
        this.sign = this.add.image(512, -200, 'https://labs.phaser.io/assets', 'levelComplete');
        this.sound.play('levelComplete');
        this.tweens.add({
            targets: this.sign,
            y: 384,
            ease: 'Bounce.easeOut',
            duration: 1500,
            onComplete: () => {
                this.input.once('pointerdown', () => this.nextLevel());
            }
        });
    }
    nextLevel ()
    {
        this.goals.forEach((goal, index) => {
            goal.setFrame((index + 1).toString());
            goal.setVisible(true);
        });
        this.gold.getChildren().forEach((gold) => {
            gold.setVisible(false);
            gold.setActive(false);
        });
        //  Reset everything
        this.doors.forEach((door) => {
            door.reset(this.game.getTime());
        });
        this.goalsComplete = 0;
        //  Change difficulty
        if (this.level < 5)
        {
            this.killDelay -= 0.1;
        }
        if (this.level < 10)
        {
            this.closeDurationLow -= 100;
            this.closeDurationHigh -= 200;
        }
        //  Change level counter
        this.level++;
        this.levelImage.setFrame(this.level);
        this.sign.setVisible(false);
        this.isPaused = false;
    }
    killed (x, y)
    {
        //  Bullet holes on the screen
        let offsetX = 100;
        for (let i = 0; i < 3; i++)
        {
            let x = Phaser.Math.RND.between(offsetX, offsetX + 200);
            let y = Phaser.Math.RND.between(200, 600);
            let hole = this.add.image(x, y, 'bulletHole').setAlpha(0);
            this.tweens.add({
                targets: hole,
                alpha: 1,
                duration: 30,
                delay: 200 * i
            });
            offsetX += 340;
        }
        this.levelFail();
    }
    update (time)
    {
        if (!this.isPaused)
        {
            this.doors.forEach((door) => {
                door.update(time);
            });
        }
    }
}
            import Boot from './Boot.js';
import Preloader from './Preloader.js';
import MainMenu from './MainMenu.js';
import MainGame from './Game.js';
const config = {
    type: Phaser.AUTO,
    width: 1024,
    height: 768,
    backgroundColor: '#2e91f3',
    parent: 'phaser-example',
    scene: [ Boot, Preloader, MainMenu, MainGame ]
};
let game = new Phaser.Game(config);
            export default class Door extends Phaser.GameObjects.Container
{
    constructor (name, scene, x, y)
    {
        super(scene, x, y);
        this.name = name;
        this.background = scene.add.image(0, 0, 'https://labs.phaser.io/assets', 'doorBackground');
        this.door = scene.add.sprite(0, 0, 'https://labs.phaser.io/assets', 'door1');
        this.character = scene.add.image(0, 0, 'https://labs.phaser.io/assets', 'bandit1');
        this.characterFrame = 'bandit1';
        this.isOpen = false;
        this.isBandit = false;
        this.isHats = false;
        this.isDead = false;
        this.wasBandit = (scene.doors.length % 2) ? true : false;
        this.hats = 0;
        this.timeToOpen = Number.MAX_SAFE_INTEGER;
        this.timeToClose = Number.MAX_SAFE_INTEGER;
        this.timeToKill = 0;
        this.characters = [
            'bandit1',
            'bandit2',
            'cowboy1',
            'cowboy2',
            'hat'
        ];
        this.add([ this.background, this.character, this.door ]);
        this.setSize(200, 400);
        this.setInteractive();
        this.on('pointerup', this.shoot, this);
        scene.add.existing(this);
    }
    destroy ()
    {
        this.off('pointerup');
    }
    start (time)
    {
        this.timeToOpen = time + Phaser.Math.RND.between(500, 4000);
    }
    reset (time)
    {
        this.isOpen = false;
        this.isBandit = false;
        this.isHats = false;
        this.isDead = false;
        this.door.play('doorClose');
        this.timeToOpen = time + Phaser.Math.RND.between(500, 4000);
    }
    openDoor (time)
    {
        this.isOpen = true;
        this.isBandit = false;
        this.isHats = false;
        this.isDead = false;
        this.characterFrame = Phaser.Utils.Array.GetRandom(this.characters);
        //  When should this door close again?
        const duration = Phaser.Math.RND.between(this.scene.closeDurationLow, this.scene.closeDurationHigh);
        this.timeToClose = time + duration;
        if (this.characterFrame === 'bandit1' || this.characterFrame === 'bandit2')
        {
            this.isBandit = true;
        }
        else if (this.characterFrame === 'hat')
        {
            this.isHats = true;
            //  Pick random number of hats
            this.hats = Phaser.Math.RND.between(2, 5);
            this.characterFrame += this.hats.toString();
        }
        else
        {
            this.timeToClose = time + (duration / 2);
        }
        //  If we had a citizen or hats on our last go, we have to have a bandit now
        if (!this.wasBandit && !this.isBandit)
        {
            this.isHats = false;
            this.hats = 0;
            this.isBandit = true;
            this.characterFrame = (Math.random() > 0.5) ? 'bandit1' : 'bandit2';
            this.timeToClose = time + duration;
        }
        this.character.setFrame(this.characterFrame);
        this.character.setScale(1).setAlpha(1);
        if (this.isBandit)
        {
            this.timeToKill = time + (duration * this.scene.killDelay);
        }
        this.scene.sound.play('door');
        this.door.play('doorOpen');
    }
    closeDoor (time)
    {
        this.door.play('doorClose');
        this.isOpen = false;
        this.wasBandit = this.isBandit;
        if (!this.isBandit && !this.isHats && !this.isDead)
        {
            this.scene.addGold(this.x, this.y);
        }
        //  When should this door open again?
        this.timeToOpen = time + Phaser.Math.RND.between(2000, 4000);
    }
    shoot ()
    {
        if (!this.isOpen || this.scene.isPaused)
        {
            return;
        }
        this.scene.sound.play('shot');
        if (this.isDead)
        {
            //  We will want to hear the gunshot, but not actually do anything with it
            return;
        }
        if (this.isBandit)
        {
            this.shootCharacter(true);
        }
        else
        {
            if (this.isHats)
            {
                this.shootHat();
            }
            else
            {
                this.shootCharacter(false);
            }
        }
    }
    shootCharacter (closeDoor)
    {
        this.isDead = true;
        this.characterFrame += 'Dead';
        this.character.setFrame(this.characterFrame);
        this.scene.sound.play('scream' + Phaser.Math.RND.between(1, 3));
        this.scene.tweens.add({
            targets: this.character,
            scaleX: 0.5,
            scaleY: 0.5,
            duration: 300,
            onComplete: () => {
                if (closeDoor)
                {
                    this.closeDoor(this.scene.game.getTime());
                }
                else
                {
                    this.scene.levelFail();
                }
            }
        });
        //  No more shots at this door
        if (!closeDoor)
        {
            this.off('pointerup');
            this.scene.isPaused = true;
        }
    }
    shootHat ()
    {
        if (this.hats > 0)
        {
            this.scene.addHat(this.x, this.y, this.hats);
            this.hats--;
            this.characterFrame = 'hat' + this.hats;
        }
        this.character.setFrame(this.characterFrame);
    }
    shootYou ()
    {
        this.off('pointerup');
        this.scene.isPaused = true;
        //  Shots
        let shot1 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'shot1');
        let shot2 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'shot2');
        this.scene.sound.play('banditShot');
        this.scene.sound.play('banditShot', { delay: 0.25 });
        this.scene.sound.play('banditShot', { delay: 0.5 });
        this.scene.tweens.add({
            targets: shot1,
            alpha: 0,
            duration: 200,
            ease: 'Power2'
        });
        this.scene.tweens.add({
            targets: shot2,
            alpha: 0,
            duration: 200,
            delay: 200,
            ease: 'Power2',
            onComplete: () => {
                this.scene.killed(this.x, this.y);
            }
        });
        //  Gun smoke rising from the bandit
        let smoke1 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'smoke1');
        let smoke2 = this.scene.add.image(this.x, this.y, 'https://labs.phaser.io/assets', this.characterFrame + 'smoke2');
        this.scene.tweens.add({
            targets: smoke1,
            props: {
                y: { value: 150, duration: 1000, ease: 'Sine.easeInOut' },
                alpha: { value: 0, duration: 250, ease: 'Power2', delay: 750 }
            }
        });
        this.scene.tweens.add({
            targets: smoke2,
            props: {
                y: { value: 150, duration: 1000, ease: 'Sine.easeInOut', delay: 500 },
                alpha: { value: 0, duration: 250, ease: 'Power2', delay: 1250 }
            }
        });
    }
    update (time)
    {
        if (!this.isOpen && time >= this.timeToOpen)
        {
            this.openDoor(time);
        }
        else if (this.isOpen && time >= this.timeToClose)
        {
            this.closeDoor(time);
        }
        else if (this.isOpen && this.isBandit && !this.isDead && time >= this.timeToKill)
        {
            this.shootYou();
        }
    }
}