phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
36.64k stars 7.07k forks source link

postFX Wipe is not affecting the Sprite on first frame #6836

Closed Overld closed 2 weeks ago

Overld commented 2 weeks ago

Version

Description

When using the Wipe to bring the object to the screen, it will flash the full object briefly, and then the Wipe effect will take effect. It works correctly in preFX, but not in postFX. The object I am using is too complicated for preFX.

Example Test Code

The code examples that show the issues are from this repo. https://github.com/phaserjs/examples

This version of the code was modified from src\fx\wipe\reveal bottom Phaser 3 Examples.

class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    preload ()
    {
        this.load.image('pyramid', 'assets/sprites/pyramid.png');
        this.load.image('bg', 'assets/skies/space4.png');
    }

    create ()
    {
        this.add.image(400, 300, 'bg');

        this.pyramid = this.add.image(400, 300, 'pyramid');

        this.fadeOutPyramid();
    }

    fadeInPyramid()
    {
        // Fade in the Reels and Reel Symbols (Top to Bottom)
        this.pyramid.setVisible(false);
        let fx = this.pyramid.postFX.addReveal(0.1, 1, 1);

        this.fadeInTween = this.tweens.add({
            targets: fx,
            progress: 1.0,
            yoyo: false,
            repeat: 0,
            duration: 2000,
            callbackScope: this,
            onStart: () => {
                this.pyramid.setVisible(true);
            },
            onComplete: () => {
                this.pyramid.postFX.clear();
                this.fadeOutPyramid();
            }
        });
    }

    fadeOutPyramid()
    {
        // Fade out the Pyramid
        let fx = this.pyramid.postFX.addWipe(0.1, 1, 1);

        this.tweens.add({
            targets: fx,
            progress: 1,
            yoyo: false,
            repeat: 0,
            duration: 2000,
            callbackScope: this,
            onComplete: () => {
                this.pyramid.postFX.clear();
                this.pyramid.setVisible(false);        
                this.fadeInPyramid();
            }
        });
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#0a0067',
    parent: 'phaser-example',
    scene: Example
};

let game = new Phaser.Game(config);

Additional Information

For this example, in my game, I will call fadeOutPyramid() to remove the object, and then gameplay will continue for several minutes. When finished I will call fadeInPyramid() to return the game to normal operations. If I don't set the object to visible, then the fadeInPyramid() will do nothing. I tried setting it to visible when progress gets to a certain point, but it didn't prevent the flash. I left the object hidden until it was 0.5 progress, and in an onUpdate() in the tween I would set it to visible, but it would still flash. This issue did not occur in version 3.60

zekeatchan commented 2 weeks ago

Wipe and Reveal are essentially the same FX. When using addReveal you are just adding a boolean flag that reverses the way the FX works.

Using your code example, here's a suggestion on how to go about this.

Use this.fx = this.pyramid.postFX.addWipe(0.1, 1, 1); to add the FX once, then modify its properties.

Replace the create, fadeInPyramid and fadeOutPyramid functions in your example:

    create ()
    {
        this.add.image(400, 300, 'bg');

        this.pyramid = this.add.image(400, 300, 'pyramid');
        this.fx = this.pyramid.postFX.addWipe(0.1, 1, 1);

        this.fadeOutPyramid();
    }

    fadeInPyramid()
    {
        this.fx.progress = 0;
        this.fx.reveal = true;

        this.tweens.add({
            targets: this.fx,
            progress: 1,
            duration: 2000,
            callbackScope: this,
            onComplete: () => {
                this.fadeOutPyramid();
            }
        });
    }

    fadeOutPyramid()
    {
        this.fx.progress = 0;
        this.fx.reveal = false;

        this.tweens.add({
            targets: this.fx,
            progress: 1,
            duration: 2000,
            callbackScope: this,
            onComplete: () => {
                this.fadeInPyramid();
            }
        });
    }
Overld commented 2 weeks ago

Your solution works perfectly in my actual game. I do not see any glitching, and this code is much simpler. This helps expand my understanding of FX, and thank you very much for your assistance.