Jump to content

[CLOSED] Phaser 3.13.0 - Rendering Bug in WebGL?


jamespierce
 Share

Recommended Posts

@rich in the scene's main update loop:

CombatScene.update = function()
{
	'use strict';
	
	if(this.trigger_intro)
	{
		this.trigger_intro = false;
		
		let veil = this.add.graphics({ x: 0, y: 0 });
		veil.fillStyle(0x000000, 1);
		veil.fillRect(0, 0, this._CONFIG.width, this._CONFIG.height);	
		veil.setDepth(this.DEPTH.veil);
	}
};

 

23 hours ago, rich said:

I bet if, instead of actually creating the Graphics object in the callback, you just set a flag - and then during your main update loop you check for this flag, and if set, create the Graphics object, then it'd work fine because it would all be within the expected flow.

I was trying to implement it according to your comment yesterday - maybe I misunderstood or did it wrong.

The code I posted in my comment just previous to this one follows these steps:

  1. In the scene's create method I execute the ajax call to fetch data from the server.
  2. The callback function of said ajax call sets the trigger_intro flag to true.
  3. In the scene's main update loop, if the flag is set to true, it creates the graphics object.
Link to comment
Share on other sites

It's got to be a combination of things on the display list, or Scene order, it really can't be anything else.

I tried to re-create your set-up (see below) but it works, so there's a piece of the puzzle missing:

class BaseScene extends Phaser.Scene {

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

    preload ()
    {
        this.load.image('bunny', 'assets/sprites/bunny.png');
    }

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

        var text = this.add.text(10, 10, 'click it', { font: '16px Courier', fill: '#00ff00' });

        this.input.once('pointerdown', function () {

            var combat = this.scene.get('combat');

            combat.makeIt = true;

        }, this);
    }

}

class CombatScene extends Phaser.Scene {

    constructor ()
    {
        super({ key: 'combat', active: true });

        this.makeIt = false;
    }

    update ()
    {
        if (this.makeIt)
        {
            this.makeIt = false;

            let veil = this.add.graphics({ x: 0, y: 0 });

            veil.fillStyle(0xff0000, 1);
            veil.fillRect(0, 0, 320, 200);
            veil.setDepth(100);
        }
    }

}

var config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: [ BaseScene, CombatScene ]
};

var game = new Phaser.Game(config);

 

Link to comment
Share on other sites

@rich The difference is you are using the click input to trigger the graphics creation. I don't have any errors either for callbacks to an input event. It only happens if I do an ajax call and the callback waits for the server response. The exact combination to trigger the error for me is this:

  • The scene's create method triggers an ajax call
  • We wait for the ajax call to complete before we run the callback function
  • Inside the callback function we create a graphics object and use it to draw something

The solution with setting flags runs like this:

  • The scene's create method triggers an ajax call
  • We wait for the ajax call to complete before we run the callback function
  • Inside the callback function we set the flag to true
  • Inside the scene's main update loop, we check for the flag to be true. When true we create a graphics object and use it to draw something

The crucial part is this "waiting for a response" part. Even if it's just a fraction of a second, but this "waiting" is making the error appear. If for example I pass a callback to the ajax call, and I run the callback immediately instead of waiting for a server response, there is no error either.

Link to comment
Share on other sites

Even with an ajax call it still works:

class BaseScene extends Phaser.Scene {

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

    preload ()
    {
        this.load.image('bunny', 'assets/sprites/bunny.png');
    }

    create ()
    {
        this.add.graphics().fillStyle(0xff00ff, 0.5).fillRect(200, 200, 400, 200);

        this.add.image(400, 300, 'bunny');

        var text = this.add.text(10, 10, 'click it', { font: '16px Courier', fill: '#00ff00' });

        this.input.once('pointerdown', function ()
        {
            var combat = this.scene.get('combat');

            $.ajax({
                url: "https://reqres.in/api/users",
                type: "POST",
                data: {
                    name: "arnie",
                    movies: ["Terminator 2"]
                },
                success: function (response)
                {
                    console.log('loaded', response);

                    combat.makeIt = true;
                }
            });

        }, this);
    }

}

class CombatScene extends Phaser.Scene {

    constructor ()
    {
        super({ key: 'combat', active: true });

        this.makeIt = false;
    }

    update ()
    {
        if (this.makeIt)
        {
            this.makeIt = false;

            let veil = this.add.graphics({ x: 0, y: 0 });

            veil.fillStyle(0xff0000, 1);
            veil.fillRect(0, 0, 320, 200);
            veil.setDepth(100);
        }
    }

}

var config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: [ BaseScene, CombatScene ]
};

var game = new Phaser.Game(config);

 

Link to comment
Share on other sites

@rich Okay so if I adjust your example with the exact steps that are happening in my game, I am able to replicate the errors. You should be able to copy-paste the code below and run immediately, and see the errors. The key differences are:

  • The CombatScene needs the "create" method, from which the time-event (or Ajax call, it doesn't matter as long as we are "waiting" for something) is triggered.
  • The input-event "click" needs to start the CombatScene.
  • The CombatScene needs a text object that gets destroyed in the callback... (just found that out now with your example above)
  • The CombatScene needs a callback function that handles the flagging, in the snippet below it's called "handleCallback"

To give just a little context to all these steps because you are probably thinking "how the hell did you come up with these specific circumstances":
I need the text object because I am writing on the screen "Loading..." while the client is waiting for the server sending back the player data, which is required for combat.
I am drawing this graphics object as a "veil" on top of everything that fades out and make a smooth transition.
So what's happening is: (1) Enter CombatScene, (2) Write "Loading..." on the screen while we wait for player data from game server, (3) when data arrives: destroy the "Loading..." text and draw the black rectangle on top of everything and fade it out to create a smooth transition.

Anyways, stripping out everything except for the essentials that are causing the error, we end up with the code below. I commented where I added the parts to your example.

I also uploaded the whole example below to my website here, so you can test immediately: http://browsergameshub.com/gameapps/ErrorTesting/
Direct link to the JS file: http://browsergameshub.com/gameapps/ErrorTesting/boot.js

class BaseScene extends Phaser.Scene {

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

    preload ()
    {
        this.load.image('bunny', 'assets/sprites/bunny.png');
    }

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

        var text = this.add.text(10, 10, 'click it', { font: '16px Courier', fill: '#00ff00' });

        this.input.once('pointerdown', function () {

            var combat = this.scene.get('combat');

            combat.makeIt = true;
			
			this.scene.start('combat'); // I added this
		}, this);
	}
}


class CombatScene extends Phaser.Scene {

    constructor ()
    {
        super({ key: 'combat', active: true });

        this.makeIt = false;
    }
	
	create () // I added this
	{
		this.text = this.add.text(10, 10, 'CombatScene', { font: '16px Courier', fill: '#00ff00' });
		
		this.time.addEvent({
			delay: 100,
			callback: this.handleCallback,
			callbackScope: this
		});
	}
	
    update ()
    {
        if (this.makeIt)
        {
            this.makeIt = false;

            let veil = this.add.graphics({ x: 100, y: 100 });

            veil.fillStyle(0xff0000, 1);
            veil.fillRect(0, 0, 320, 200);
            veil.setDepth(100);
        }
    }
	
	handleCallback () // I added this
	{
		this.text.destroy(); // Don't destroy the text object and there should be no errors
		
		this.makeIt = true;
	}

}

var config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: [ BaseScene, CombatScene ]
};

var game = new Phaser.Game(config);

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...