Phaser3 preFX addGlow doesn't work with scaling

58 views Asked by At

I'm trying to use Phaser3 .. currently tried 3.70 and the 3.80 beta with no avail. If I try to use someSprite.preFX.addGLow() it works when there is no scaling, but if I use scaling the sprites completely disappear.

Config that doesn't work:

<html>
    <body>
        <script src="https://cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
        <script>

class BrokenScene extends Phaser.Scene
{
    GAME_WIDTH = 640;
    GAME_HEIGHT = 960;

    sizer;
    player;
    player2;
    platforms;

    constructor () {
        super('GameScene');
    }

    preload() {
        this.load.spritesheet('dude', 'https://labs.phaser.io/assets/sprites/dude.png', { frameWidth: 32, frameHeight: 48 });
        this.load.image('ground', 'https://labs.phaser.io/assets/sprites/platform.png');
    }

    create () {

        const width = this.scale.gameSize.width;
        const height = this.scale.gameSize.height;

        this.parent = new Phaser.Structs.Size(width, height);
        this.sizer = new Phaser.Structs.Size(this.GAME_WIDTH, this.GAME_HEIGHT, Phaser.Structs.Size.FIT, this.parent);

        this.parent.setSize(width, height);
        this.sizer.setSize(width, height);

        this.updateCamera();

        this.scale.on('resize', this.resize, this);

        this.physics.world.setBounds(0, 0, this.GAME_WIDTH, this.GAME_HEIGHT);

        //  The platforms group contains the ground and the 2 ledges we can jump on
        this.platforms = this.physics.add.staticGroup();
        this.platforms.setDepth(10);

        //  Here we create the ground.
        //  Scale it to fit the width of the game (the original sprite is 400x32 in size)
        this.platforms.create(320, 944, 'ground').setDisplaySize(640, 32).setDepth(10).refreshBody();
     

        // -----------------------[ The glow section ]----------------------------- // 
        // This one fails... with preFX
        this.player = this.physics.add.sprite(100, 800, 'dude');

        this.player.preFX.setPadding(32);
        const fx = this.player.preFX.addGlow();

        // This one works with postFX
        this.player2 = this.physics.add.sprite(250, 800, 'dude');

        this.player2.postFX.setPadding(32);
        const fx2 = this.player2.postFX.addGlow();

        //  For PreFX Glow the quality and distance are set in the Game Configuration
        this.tweens.add({
            targets: [fx, fx2],
            outerStrength: 10,
            yoyo: true,
            loop: -1,
            ease: 'sine.inout'
        });

        // -----------------------[ end glow section ]----------------------------- // 


        this.player.setBounce(0.1);
        this.player.setCollideWorldBounds(true);
        this.player.setDepth(1);

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

    //  Resize related functions
    resize (gameSize) {
        const width = gameSize.width;
        const height = gameSize.height;

        this.parent.setSize(width, height);
        this.sizer.setSize(width, height);

        this.updateCamera();
    }

    updateCamera () {
        const camera = this.cameras.main;

        const x = Math.ceil((this.parent.width - this.sizer.width) * 0.5);
        const y = 0;
        const scaleX = this.sizer.width / this.GAME_WIDTH;
        const scaleY = this.sizer.height / this.GAME_HEIGHT;

        camera.setViewport(x, y, this.sizer.width, this.sizer.height);
        camera.setZoom(Math.max(scaleX, scaleY));
        camera.centerOn(this.GAME_WIDTH / 2, this.GAME_HEIGHT / 2);
    }

    getZoom () {
        return this.cameras.main.zoom;
    }

    update () {}
}

const config = {
        type: Phaser.AUTO,
        backgroundColor: '#000000',
        scale: {
            mode: Phaser.Scale.RESIZE,
            width: 640,
            height: 960,
            min: {
                width: 320,
                height: 480
            },
            max: {
                width: 1400,
                height: 1200
            }
        },
        scene: [ BrokenScene ],
        fx: {
            glow: {
                distance: 32,
                quality: 0.1
            }
        },
        physics: {
            default: 'arcade',
            arcade: {
                gravity: { y: 300 },
                debug: false
            }
        }
    };

    const game = new Phaser.Game(config);

        </script>
    </body>
</html>

any suggestions what's wrong? If I use postFX it does render, but the Phaser examples I saw (without scaling) had suggested preFX.

1

There are 1 answers

2
winner_joiner On BEST ANSWER

Could you create a minimal reproducible Example, since the code seems to work for me, see the code below.

Mini Demo:

document.body.style = 'margin:0;';

var config = {
    type: Phaser.AUTO,

    scene: {
        create
    },
    scale: {
        mode: Phaser.Scale.RESIZE,
        width: 640,
        height: 960,
        min: {
            width: 100,
            height: 52
        },
        max: {
    width: 536,
    height: 183,
        }
    },
     fx: { // Glow FX settings... 
        glow: {
            distance: 32,
            quality: 0.1
        }
    },
}; 

function create () {
    this.add.text(10,10, 'DEMO TEXT')
        .setScale(1.5)
        .setOrigin(0)
        .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});

    let graphics  = this.make.graphics();
    graphics.fillStyle(0xffffff);
    graphics.fillRect(0, 0, 10, 10);
    graphics.generateTexture('img', 10, 10);

    let img1 = this.add.image(50, 50, 'img');
    
    let img2 = this.add.sprite(150, 50, 'img')
      .setScale(2);
    
    img1.preFX.setPadding(32);
    const fx = img1.preFX.addGlow();
    
    img2.preFX.setPadding(32);
    const fx2 = img2.preFX.addGlow();
    
   this.tweens.add({
        targets: [fx, fx2],
        outerStrength: 10,
        yoyo: true,
        loop: -1,
        ease: 'sine.inout'
    });
}

new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

Update:

I did some test, and now I assume the isseue has to due with the Phaser.Structs.Size in conjunction with preFX, and some rendering order/race-condition.

  1. Since if you replace Phaser.Struct.Size.FIT with Phaser.Struct.Size.NONE both sprites are show.

  2. If you pack the whole screen resizing in to a setTimeout so that phaser has time to render/Calculate stuff, it also works.

like this:

    setTimeout( () => {

        this.parent = new Phaser.Structs.Size(width, height);
        this.sizer = new Phaser.Structs.Size(this.GAME_WIDTH, this.GAME_HEIGHT, Phaser.Structs.Size.FIT, this.parent);

        this.parent.setSize(width, height);
        this.sizer.setSize(width, height);

        this.updateCamera(); 
     }, 10);

This seems like this must be a bug. I would recommend using the postFx for now and posting this issue in the https://phaser.discourse.group/ and/or as an issue in github project (Or if you feel adventures on the discord server). The developers are usually very helpful, and they might be able to solve it vor der release of 3.8.