HTML5 Game Development

with Phaser

Matt Wilber

@greenzeta

greenzeta.com

Browser Game Portfolio

Combat 2077

Flash 4

Visionary Media 2000

Acme Agent Hunter

Flash 5

Warner Bros. 2003

Go Turtle Go!

Flash 8

Little Tikes 2011

Peanut Butter Art

EaselJS

Hormel 2015

Smashion

Phaser

VFiles 2016

Puppy Club

Phaser / Cordova

Mini Trading Cards Co. 2018

Browser Game History

...the short version

First, there was Flash. And it was good...

But it required a plug-in.

Then HTML5 gave us <canvas>,

which had everything...

Except an easy way to use it.

This led to the creation of, many,

specialized frameworks.

Phaser

Open Source HTML <canvas> game development framework that's "fast fun and free"

  • WEBGL & CANVAS
  • PRELOADER
  • PHYSICS
  • SPRITES
  • GROUPS
  • ANIMATION
  • PARTICLES
  • CAMERA
  • INPUT
  • SOUND
  • TILEMAPS
  • DEVICE SCALING
  • PLUGIN SYSTEM
  • DEVELOPER SUPPORT
  • MOBILE BROWSER
  • WEB FIRST

A Brief Word on

“Modern” JavaScript

ECMA Script 2015 (ES6)

  • Modules
  • Class Syntax

Webpack & Babel

  • Bundling
  • Polyfill Injection
  • Development Server
    • Live reloading. YAY!

Node Package Manager (npm)

  • Libraries on demand
  • Custom CLI scripts

Let's Make a Game!

Start with the GreenZeta Webpack Boilerplate

github.com/mwilber/gz-webpack-boilerplate

Installing Phaser

import 'phaser';

src/main.js

npm install --save phaser

CLI

github.com/mwilber/zeta-bros  >  Step1

Game Object / Config

import { GameScene } from './scenes/GameScene';

const gameConfig = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-game',
    dom: {
        createContainer: true
    },
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 900 },
            debug: false
        }
    },
    scene: [
        GameScene
    ]
};

new Phaser.Game(gameConfig);

src/main.js

github.com/mwilber/zeta-bros  >  Step2

Game Scene

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
	super({
            key: 'GameScene'
        });
    }

    preload() {
        this.load.image('background', 'assets/images/background.png');
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');
    }

    update() {

    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step3

Player Character

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
	super({
            key: 'GameScene'
        });
    }

    preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.player = this.createPlayer();
    }

    update() {

    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step4

Controls

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
		super({
            key: 'GameScene'
        });
	}

	preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.cursors = this.input.keyboard.createCursorKeys();

        this.player = this.createPlayer();
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
        }else{
            this.player.setVelocityX(0);
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step5

Animation

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
	super({
            key: 'GameScene'
        });
    }

    preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.initAnimation();

        this.cursors = this.input.keyboard.createCursorKeys();

        this.player = this.createPlayer();
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
            this.player.anims.play('left', true);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
            this.player.anims.play('right', true);
        }else{
            this.player.setVelocityX(0);
            this.player.anims.play('turn');
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }

    initAnimation() {
        this.anims.create({
            key: 'left',
            frames: this.anims.generateFrameNumbers('zeta', { start: 0, end: 3 }),
            frameRate: 30,
            repeat: -1
        });

        this.anims.create({
            key: 'turn',
            frames: [ { key: 'zeta', frame: 4 } ],
            frameRate: 30
        });

        this.anims.create({
            key: 'right',
            frames: this.anims.generateFrameNumbers('zeta', { start: 5, end: 8 }),
            frameRate: 30,
            repeat: -1
        });
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step6

Platforms

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
	super({
            key: 'GameScene'
        });
    }

    preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.image('ground', 'assets/images/ground.png');
        this.load.image('wall', 'assets/images/wall.png');
        this.load.image('platform', 'assets/images/platform.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.initAnimation();

        this.cursors = this.input.keyboard.createCursorKeys();

        this.platforms      = this.createPlatforms();
        this.player         = this.createPlayer();
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
            this.player.anims.play('left', true);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
            this.player.anims.play('right', true);
        }else{
            this.player.setVelocityX(0);
            this.player.anims.play('turn');
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createPlatforms() {
        let platforms = this.physics.add.staticGroup();

        platforms.create(400, 270, 'platform');

        platforms.create(400, 572, 'ground');

        return platforms;
    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }

    initAnimation() {
        this.anims.create({
            key: 'left',
            frames: this.anims.generateFrameNumbers('zeta', { start: 0, end: 3 }),
            frameRate: 30,
            repeat: -1
        });

        this.anims.create({
            key: 'turn',
            frames: [ { key: 'zeta', frame: 4 } ],
            frameRate: 30
        });

        this.anims.create({
            key: 'right',
            frames: this.anims.generateFrameNumbers('zeta', { start: 5, end: 8 }),
            frameRate: 30,
            repeat: -1
        });
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step7

Collider

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
		super({
            key: 'GameScene'
        });
	}

	preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.image('ground', 'assets/images/ground.png');
        this.load.image('wall', 'assets/images/wall.png');
        this.load.image('platform', 'assets/images/platform.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.initAnimation();

        this.cursors = this.input.keyboard.createCursorKeys();

        this.platforms      = this.createPlatforms();
        this.player         = this.createPlayer();

        this.physics.add.collider(this.player, this.platforms);
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
            this.player.anims.play('left', true);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
            this.player.anims.play('right', true);
        }else{
            this.player.setVelocityX(0);
            this.player.anims.play('turn');
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createPlatforms() {
        let platforms = this.physics.add.staticGroup();

        platforms.create(400, 270, 'platform');

        platforms.create(400, 572, 'ground');

        return platforms;
    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }

    initAnimation() {
        this.anims.create({
            key: 'left',
            frames: this.anims.generateFrameNumbers('zeta', { start: 0, end: 3 }),
            frameRate: 30,
            repeat: -1
        });

        this.anims.create({
            key: 'turn',
            frames: [ { key: 'zeta', frame: 4 } ],
            frameRate: 30
        });

        this.anims.create({
            key: 'right',
            frames: this.anims.generateFrameNumbers('zeta', { start: 5, end: 8 }),
            frameRate: 30,
            repeat: -1
        });
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step8

Enemy Bot

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
		super({
            key: 'GameScene'
        });
	}

	preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.image('ground', 'assets/images/ground.png');
        this.load.image('wall', 'assets/images/wall.png');
        this.load.image('platform', 'assets/images/platform.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
        this.load.image('bot', 'assets/images/security_bot.png')
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.initAnimation();

        this.cursors = this.input.keyboard.createCursorKeys();

        this.platforms      = this.createPlatforms();
        this.player         = this.createPlayer();
        this.bots = this.physics.add.group();

        this.physics.add.collider(this.player, this.platforms);
        this.physics.add.collider(this.bots, this.platforms);

        this.spawnBot();
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
            this.player.anims.play('left', true);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
            this.player.anims.play('right', true);
        }else{
            this.player.setVelocityX(0);
            this.player.anims.play('turn');
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createPlatforms() {
        let platforms = this.physics.add.staticGroup();

        platforms.create(400, 270, 'platform');

        platforms.create(400, 572, 'ground');

        return platforms;
    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }

    initAnimation() {
        this.anims.create({
            key: 'left',
            frames: this.anims.generateFrameNumbers('zeta', { start: 0, end: 3 }),
            frameRate: 30,
            repeat: -1
        });

        this.anims.create({
            key: 'turn',
            frames: [ { key: 'zeta', frame: 4 } ],
            frameRate: 30
        });

        this.anims.create({
            key: 'right',
            frames: this.anims.generateFrameNumbers('zeta', { start: 5, end: 8 }),
            frameRate: 30,
            repeat: -1
        });
    }

    spawnBot(){
        this.bots.create(100, 75, 'bot').setVelocityX(100);
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step9

Collision Handler

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
		super({
            key: 'GameScene'
        });
	}

	preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.image('ground', 'assets/images/ground.png');
        this.load.image('wall', 'assets/images/wall.png');
        this.load.image('platform', 'assets/images/platform.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
        this.load.image('bot', 'assets/images/security_bot.png')
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.initAnimation();

        this.cursors = this.input.keyboard.createCursorKeys();

        this.platforms      = this.createPlatforms();
        this.walls          = this.createWalls();
        this.player         = this.createPlayer();
        this.bots = this.physics.add.group();

        this.physics.add.collider(this.player, this.platforms);
        this.physics.add.collider(this.bots, this.platforms);
        this.physics.add.collider(this.bots, this.walls, this.handleCollisionWall.bind(this));
        this.physics.add.collider(this.player, this.bots, this.handleCollisionEnemy.bind(this));

        this.spawnBot();
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
            this.player.anims.play('left', true);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
            this.player.anims.play('right', true);
        }else{
            this.player.setVelocityX(0);
            this.player.anims.play('turn');
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createPlatforms() {
        let platforms = this.physics.add.staticGroup();

        platforms.create(400, 270, 'platform');

        platforms.create(400, 572, 'ground');

        return platforms;
    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }

    createWalls() {
        let walls = this.physics.add.staticGroup();

        walls.create(0, 300, 'wall').setActive(true);
        walls.create(800, 300, 'wall').setActive(true);

        return walls;
    }

    handleCollisionWall(event, collider){
        if(collider.body.touching.left){
            event.setVelocityX(-100);
        }else if(collider.body.touching.right){
            event.setVelocityX(100);
        }

        return true;
    }

    handleCollisionEnemy(event, collider) {
        this.scene.start('EndScene');
    }

    initAnimation() {
        this.anims.create({
            key: 'left',
            frames: this.anims.generateFrameNumbers('zeta', { start: 0, end: 3 }),
            frameRate: 30,
            repeat: -1
        });

        this.anims.create({
            key: 'turn',
            frames: [ { key: 'zeta', frame: 4 } ],
            frameRate: 30
        });

        this.anims.create({
            key: 'right',
            frames: this.anims.generateFrameNumbers('zeta', { start: 5, end: 8 }),
            frameRate: 30,
            repeat: -1
        });
    }

    spawnBot(){
        this.bots.create(100, 75, 'bot').setVelocityX(100);
    }
    
}

src/scenes/GameScene.js

github.com/mwilber/zeta-bros  >  Step10

End Scene

github.com/mwilber/zeta-bros  >  Step11

import 'phaser';
import { GameScene } from './scenes/GameScene';
import { EndScene } from './scenes/EndScene';

const gameConfig = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-game',
    dom: {
        createContainer: true
    },
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 900 },
            debug: false
        }
    },
    scene: [
        GameScene,
        EndScene
    ]
};

new Phaser.Game(gameConfig);

src/main.js

import Phaser from 'phaser';

export class EndScene extends Phaser.Scene {
    constructor() {
		super({
			key: 'EndScene'
        });

	}

	preload() {
        this.load.image('end_splash', 'assets/images/end_splash.png');
    }

    create() {
        // Add the background image
        this.splash = this.add.image(400, 300, 'end_splash');

        this.splash.setInteractive().on('pointerdown', () => { 
            this.scene.start('IntroScene');
        });
    }
} 

src/scenes/EndScene.js

import Phaser from 'phaser';

export class GameScene extends Phaser.Scene {
    constructor() {
		super({
            key: 'GameScene'
        });

        this.levelCt = 1;
	}

	preload() {
        this.load.image('background', 'assets/images/background.png');
        this.load.image('ground', 'assets/images/ground.png');
        this.load.image('wall', 'assets/images/wall.png');
        this.load.image('platform', 'assets/images/platform.png');
        this.load.spritesheet('zeta', 
            'assets/images/zeta_spritesheet.png',
            { frameWidth: 40, frameHeight: 60 }
        );
        this.load.spritesheet('door', 
            'assets/images/door.png',
            { frameWidth: 64, frameHeight: 64 }
        );
        this.load.image('bot', 'assets/images/security_bot.png')
    }

    create() {
        // Add the background image
        this.add.image(400, 300, 'background');

        this.initAnimation();

        this.cursors = this.input.keyboard.createCursorKeys();

        this.door           = this.createDoors();
        this.doorsign       = this.createDoorSign();
        this.platforms      = this.createPlatforms();
        this.walls          = this.createWalls();
        this.player         = this.createPlayer();
        this.bots = this.physics.add.group();

        this.physics.add.collider(this.player, this.platforms);
        this.physics.add.collider(this.bots, this.platforms);
        this.physics.add.collider(this.bots, this.walls, this.handleCollisionWall.bind(this));
        this.physics.add.collider(this.player, this.bots, this.handleCollisionEnemy.bind(this));
        this.physics.add.overlap(this.player, this.door, this.handleOverlapDoor.bind(this));

        this.doorsign.setText(this.levelCt);

        this.spawnBot();
    }

    update() {

        if (this.cursors.left.isDown){
            this.player.setVelocityX(-200);
            this.player.anims.play('left', true);
        }else if (this.cursors.right.isDown){
            this.player.setVelocityX(200);
            this.player.anims.play('right', true);
        }else{
            this.player.setVelocityX(0);
            this.player.anims.play('turn');
        }

        if (this.cursors.up.isDown && this.player.body.touching.down){
            this.player.setVelocityY(-750);
        }

    }

    createDoors(){
        let door = this.physics.add.staticGroup();

        // Entry door is inactive
        door.create(400, 508, 'door', 0, true, false);

        // Add an exit door
        door.create(700, 508, 'door', 3);

        return door;
    }

    createDoorSign(){
        this.add.text(380, 410, 'LEVEL', { fontSize: '12px', fill: '#ff0000', align: 'center', fontFamily: 'sans-serif' });
        return this.add.text(385, 420, '0', { fontSize: '48px', fill: '#ff0000', align: 'center', fontFamily: 'sans-serif' });
    }

    createPlatforms() {
        let platforms = this.physics.add.staticGroup();

        platforms.create(400, 270, 'platform');

        platforms.create(400, 572, 'ground');

        return platforms;
    }

    createPlayer() {
        let player = this.physics.add.sprite(100, 450, 'zeta');

        player.setBounce(0.2);
        player.setCollideWorldBounds(true);

        return player;
    }

    createWalls() {
        let walls = this.physics.add.staticGroup();

        walls.create(0, 300, 'wall').setActive(true);
        walls.create(800, 300, 'wall').setActive(true);

        return walls;
    }

    handleCollisionWall(event, collider){
        if(collider.body.touching.left){
            event.setVelocityX(-100);
        }else if(collider.body.touching.right){
            event.setVelocityX(100);
        }

        return true;
    }

    handleCollisionEnemy(event, collider) {
        this.scene.start('EndScene');
    }

    handleOverlapDoor(event, collider) {
        if(collider.active){
            // Load the next scene
            this.scene.start(this.scene.manager.getAt(this.scene.getIndex()+1));
        }
    }

    initAnimation() {
        this.anims.create({
            key: 'left',
            frames: this.anims.generateFrameNumbers('zeta', { start: 0, end: 3 }),
            frameRate: 20,
            repeat: -1
        });

        this.anims.create({
            key: 'turn',
            frames: [ { key: 'zeta', frame: 4 } ],
            frameRate: 20
        });

        this.anims.create({
            key: 'right',
            frames: this.anims.generateFrameNumbers('zeta', { start: 5, end: 8 }),
            frameRate: 20,
            repeat: -1
        });

        this.anims.create({
            key: 'doorOpen',
            frames: this.anims.generateFrameNumbers('door', { start: 1, end: 3 }),
            frameRate: 10
        });
    }

    spawnBot(){
        this.bots.create(100, 75, 'bot').setVelocityX(100);
    }
    
}

src/scenes/GameScene.js

Level System

github.com/mwilber/zeta-bros  >  Step12

import 'phaser';
import { Level1 } from './levels/level1';
import { Level2 } from './levels/level2';
import { EndScene } from './scenes/EndScene';

const gameConfig = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-game',
    dom: {
        createContainer: true
    },
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 900 },
            debug: false
        }
    },
    scene: [
        Level1,
        Level2,
        EndScene
    ]
};

new Phaser.Game(gameConfig);

src/main.js

import { GameScene } from '../scenes/GameScene';

export class Level1 extends GameScene{
    constructor() {
		super({
			key: 'Level1'
        });

        this.levelCt = 1;

	}

    createPlatforms() {

        let platforms = super.createPlatforms();

        platforms.create(100, 180, 'platform');
        platforms.create(500, 180, 'platform');

        platforms.create(700, 360, 'platform');
        platforms.create(300, 360, 'platform');

        return platforms;
    }

    createDoors(){
        let door = super.createDoors();

        // Add an exit door
        door.create(100, 132, 'door', 3);

        return door;
    }

    create() {
        super.create();

        this.time.addEvent({
            delay: 5000,
            callback: (event)=>{
                this.spawnBot('left');
            },
            callbackScope: this,
            repeat: 1
        });
    }
    
}

src/levels/Level1.js

Splash Screen

github.com/mwilber/zeta-bros  >  Step13

import 'phaser';

import { IntroScene } from './scenes/IntroScene';
import { Level1 } from './levels/level1';
import { Level2 } from './levels/level2';
import { EndScene } from './scenes/EndScene';

const gameConfig = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-game',
    dom: {
        createContainer: true
    },
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 900 },
            debug: false
        }
    },
    scene: [
        IntroScene,
        Level1,
        Level2,
        EndScene
    ]
};

new Phaser.Game(gameConfig);

src/main.js

import Phaser from 'phaser';

export class IntroScene extends Phaser.Scene {
    constructor() {
		super({
			key: 'IntroScene'
        });

	}

	preload() {
        this.load.image('splash', 'assets/images/intro_splash.png');
    }

    create() {
        // Add the background image
        this.splash = this.add.image(400, 300, 'splash');
        
        this.splash.setInteractive().on('pointerdown', () => { 
            this.scene.start('Level1');
        });
    }
}

src/scenes/IntroScene.js

Source Code

github.com/mwilber/zeta-bros

Follow @greenzeta on Twitter

Slides

slides.com/greenzeta/phaser

greenzeta.com

Phaser Website

phaser.io

Made with Slides.com