Phaser 3 Example #2

In this example, I want to create a larger Phaser 3 scene – world with a background image.

This scene uses the prior example ( Phase 3 Examples Project – Sprite Control Example ).

BackGroundScene

class BackGroundScene extends Phaser.Scene {

    private cursors: Phaser.Types.Input.Keyboard.CursorKeys;
    private spaceship: Phaser.Physics.Arcade.Sprite;
    private pointer: Phaser.Input.Pointer;
    private touch: Phaser.Input.Pointer;
    constructor() {
        super({
            key: 'BackGroundScene'
        });
    }

    preload() {
        this.load.image('ship', 'assets/sh2.png'); //the space ship 
        this.load.image('background', 'assets/sb.jpg');//the back ground image for the scene

    }
    create() {
        console.log('BackGroundScene scene create');
        /*
            setting camera bound to the same as the world bounds will keep the camera from showing
            blank canvas outside of the background image/

            */
        this.cameras.main.setBounds(0, 0, 4000, 4000);
        this.physics.world.setBounds(0, 0, 4000, 4000);
        /*
            background images is 500x500 world is 4000x4000
            This image does not scael well, another option
            would be to display it not scaled 4 times 0,0 0,500 500,0 500,500
        */
        this.add.image(0, 0, 'background').setOrigin(0).setScale(8);
        this.spaceship = this.physics.add.sprite(this.game.scale.parentSize.width / 2, this.game.scale.parentSize.height / 2, 'ship');
        this.spaceship.setDrag(35);//https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.Components.Drag.html#setDrag
        let menuItem: Phaser.GameObjects.Text = this.add.text(15, 15, "Home", { fontFamily: 'Verdana, "Times New Roman", Tahoma, serif', fontSize: 25, color: '#3333ff' });
        menuItem.setInteractive({ cursor: 'pointer' }).on('pointerdown', () => { this.scene.start('MenuScene'); });
        menuItem.setScrollFactor(0) //I believe in Phaser 2 you could lock things to camera with fixedToCamera, https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Components.ScrollFactor.html#setScrollFactor
        this.cursors = this.input.keyboard.createCursorKeys();
        this.spaceship.setCollideWorldBounds(true);
        this.pointer = this.input.activePointer;//https://photonstorm.github.io/phaser3-docs/Phaser.Input.Pointer.html
        this.touch = this.input.pointer1;
        this.cameras.main.startFollow(this.spaceship, true, 0.05, 0.05);
    }

    update() {
        if (this.pointer.isDown) {
            this.SetVelocityAndRotation(this.pointer);
        } else if (this.touch.isDown) {
            this.SetVelocityAndRotation(this.touch);
        }

        if (this.cursors.left.isDown) {
            this.spaceship.angle -= 1;
        }
        if (this.cursors.right.isDown) {
            this.spaceship.angle += 1
        }
        if (this.cursors.up.isDown) {
            let velocity: Phaser.Math.Vector2 = new Phaser.Math.Vector2()
            this.physics.velocityFromRotation(this.spaceship.rotation, 150, velocity);
            this.spaceship.setVelocity(velocity.x, velocity.y);
        }
        if (this.cursors.down.isDown) {
            this.spaceship.setVelocity(0);
        }
    }

    SetVelocityAndRotation(pointer: Phaser.Input.Pointer) {
        let velocity: Phaser.Math.Vector2 = new Phaser.Math.Vector2();
        let pointerWorld: Phaser.Geom.Point = new Phaser.Geom.Point(pointer.worldX, pointer.worldY);
        /*
            BetweenPoints seemed to work great in the last example
            But it seemed to fail here in a larger world.
            Creating a point using the pointer world coordinates
            seems to work better but still seeing a few issues now and then.

        */
        this.spaceship.rotation = Phaser.Math.Angle.BetweenPoints(this.spaceship, pointerWorld);//https://photonstorm.github.io/phaser3-docs/Phaser.Math.Angle.html#.BetweenPoints__anchor
        this.physics.velocityFromRotation(this.spaceship.rotation, 150, velocity);//https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.ArcadePhysics.html#velocityFromRotation__anchor
        this.spaceship.setVelocity(velocity.x, velocity.y);//https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.Components.Velocity.html#setVelocity__anchor
    }
}

export default BackGroundScene

With the larger world size, the velocityFromRotation had issues. I believe because the pointer.x/y should be worldX/WorldY. Passing in those values instead seemed to correct the issues

In the last example, I had issues on my laptop if I used the touch screen I could no longer use the mouse using the activePointer.

I now use both the touch and mouse pointer instead and that does work but I still believe just using activePointer should work and will continue looking into that.

With the larger world and camera follow I found the ‘home’ to return to menu text would disappear as the sprite flew around.

In Phaser 2 you would use fixedToCamera on text/buttons you wanted to be locked to a position. After some looking through examples I found setScrollFactor allows you to lock it or semi-lock it which looks like it could be useful for other hud/motion effects.

Other Changes

Phaser Examples Menu Scene with addition of Back Ground scene
Phaser Examples Menu Scene

Besides adding the new scene/example to the menu scene I did some rewriting as in the future it will become longer and harder to work with.

class MenuScene extends Phaser.Scene {
    private menuItems: Phaser.GameObjects.Text[];

    constructor() {
        super({
            key: 'MenuScene'
        });
    }


    create(): void {
        console.log('menu scene create');
        this.menuItems = new Array<Phaser.GameObjects.Text>();
        let center = this.game.scale.parentSize.width / 2 - 275; //https://photonstorm.github.io/phaser3-docs/Phaser.Scale.ScaleManager.html#parentSize__anchor
        this.add.text(center, 25, "Phaser Examples", { fontFamily: 'Verdana, "Times New Roman", Tahoma, serif', fontSize: 64, color: '#ffffff' })
            .setTintFill(0xff0000,0x00ff00,0x0000ff,0xffffff);
        let items = Array(
            { text: "Sprite movement control (mouse / keyboard)", scene: "SpriteSpaceShipScene" },
            { text: 'Back Ground Scene', scene: 'BackGroundScene' });
        items.forEach(item => {
            this.addMenuItem(item);
        });

    }

    addMenuItem(menuItem: { text: string, scene: string }): void {

        let y: number = 100;
        y += (this.menuItems.length * 50);
        let item: Phaser.GameObjects.Text = this.add.text(this.game.scale.parentSize.width / 2 - 275, y, menuItem.text, { fontFamily: 'Verdana, "Times New Roman", Tahoma, serif', fontSize: 32, color: '#ffffff' });
        item.setInteractive({ cursor: 'pointer' }).on('pointerdown', () => { this.scene.start(menuItem.scene); });

        this.menuItems.push(item);

    }


}

export default MenuScene

This still isn’t what I have in my head but is moving closer to it. I either will consider some sort of pagination or breaking down examples into categories.

With just a couple of menu items, things work great but if I end up with dozens of examples the menu will both be hard to work with and hard for users to understand.

For now, I stopped the pointerover and pointerout events and just set a cursor: ‘pointer’

I also demonstrate setTintFill on a Phaser 3 text object.

Leave a comment

Your email address will not be published. Required fields are marked *