Nick

Phaser 2.1.3 and State Transition Plugin

Recommended Posts

I've come across a few issues in WebGL after upgrading to 2.1.3 which I've tracked down to the Phaser State Transition Plugin.

 

1. Stage is drawn upside down.

 

The State Transition Plugin makes a copy of the stage to a renderTexture like so:

this._texture = new Phaser.RenderTexture(this.game, this.game.width, this.game.height, 'cover');/* Draw the current world to the render */this._texture.renderXY(this.game.stage, -this.game.camera.x, -this.game.camera.y);
 

This results in the RenderTexture displaying the drawn stage upside down.

 

2. Error is thrown when the plugin adds a Sprite to the game which uses the new RenderTexture.

 

// Create a new sprite which uses the texture.this._cover = new Phaser.Sprite(this.game, 0, 0, this._texture);// More code to position the sprite...this.game.state.states[state]['create'] = function() { _create.call(_this.game.state.states[state]);  // This line here fires the error... _this.game.add.existing(_this._cover); _animateCover.call(_this);}this.game.state.start(state);

Once the sprite is added to the game world via add.existing() the following error fires. 

 

Uncaught TypeError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': No function was found that matched the signature provided.

 

One thing to note is that Canvas mode still works as expected.  I noticed that Phaser.RenderTexture.render now uses either renderWebGL() or renderCanvas() depending on the renderer type so the problems are specific to the WebGL implementation of renderTextures. At this stage I'm not able to shed any more light on it that that  :wacko:

 

 

 

Share this post


Link to post
Share on other sites

RenderTextures now need a matrix instead of a point object to define how they are transformed. The x/y values form the tx/ty translate values - this is handled by Phaser for drawing simple display objects, but the enter Stage may provide different. You may want to try creating a PIXI RenderTexture directly and manipulating the matrix as needed (or over-riding the Phaser render method and changing the matrix property first) as that is almost certainly the root of the issue (the matrix set-up).

Share this post


Link to post
Share on other sites

Sorry all. I've been away for a few days.

 

Thanks for the suggestions Rich. I'll be taking a look in the next couple days and will post an update here.

 

Update:

 

I've tried creating a PIXI RenderTexture directly using the following code:

/* If there's no texture create one */if (!this._texture) {  this._texture = new PIXI.RenderTexture(this.game.width, this.game.height, this.game.renderer);}this._matrix = new PIXI.Matrix();this._matrix.translate(-this.game.camera.x, -this.game.camera.y);this._texture.render(this.game.stage, this._matrix);

Again this works correctly when Canvas is the renderer but WebGL behaves the same as it did using the Phaser methods. So as far as I can tell the matrix set up is okay. 

Share this post


Link to post
Share on other sites

hmm.. can't you just work around and catch the case where webgl is used and flip the texture?  

 

do you change anything related to the world bounds in this plugin?  i am zooming in/out a lot in my game and change the bounds of the world from state to state and the camera bounds - using the plugin (change back to the menu for example) in a zoomed state results in weird bounds - not showing everything on the screen :(   

 

btw.  thank you very much for this plugin - i wish i could use it in my game.. i really like the zoom out effect on every state transition..  

 

maybe i'll find some time on this weekend to make myself familiar with the code of the plugin.. i don't know if can help but i will try :)   

 

 thx for your work!!

Share this post


Link to post
Share on other sites

it's crazy..    i played a little bit with the code of the plugin and found out that this line is turning the whole stage upside down

this._texture.renderXY(this.game.stage, this.game.camera.x, this.game.camera.y, true);

to test this i just added these two lines to my game menu:

texture = new Phaser.RenderTexture(game,game.width, game.height);texture.renderXY(game.stage, game.camera.x, game.camera.y, true);

aaaand..  everything is upside down..  not just the image.. the whole stage, physicsbodies. mouse movement... everything is mirrored along the y - axis..

 

same goes btw. for this approach:

texture = new PIXI.RenderTexture(game.width, game.height, game.renderer);matrix = new PIXI.Matrix();matrix.translate(game.camera.x, -game.camera.y);texture.render(game.stage, matrix);

rendering the game.stage on the texture flips everything :(

 

 

WTH ?  as far as i understand these lines create a new empty texture and then render the current stage on this texture..  why is this altering the stage ?

Share this post


Link to post
Share on other sites

rendering a phaser group on the texture for example does nothing...   that means it works ..

 

in my game i add everything on the stage to a group called "stageGroup" (except the game UI) for scaling

so i tried giving the render function the "stageGroup" instead of the "game.stage"  

 

it still throws the same error in the console : Error: WebGL: texImage2D: null ImageData  

but it works nevertheless..  it is still unusable for me because not everything is on the stageGroup and it doesn't take the current zoom state of the stageGroup into account and therefore looks weird.

Share this post


Link to post
Share on other sites

this code works even with my always changing zoom factors :)  

 if (!this._texture) {  this._texture = new PIXI.RenderTexture(this.game.width, this.game.height, this.game.renderer);}this._matrix = new PIXI.Matrix();this._matrix.translate(-this.game.camera.x, -this.game.camera.y);this._texture.render(this.game.world, this._matrix);

Share this post


Link to post
Share on other sites

this line still throws the old error on webGL

_this.game.add.existing(_this._cover);

the actual line in phaser.js is :  6234

  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);

maybe we should file a github issue so @rich can read this ??

Share this post


Link to post
Share on other sites

unfortunately the tween that zooms the created "cover" is not always visible on my mobile device..  the first time it is not there most of the time..   i do not understand how a tween can be skipped or just not shown but the oncomplete function is still called.

Share this post


Link to post
Share on other sites

well i found out how to make the code work and i even found a workaround for the tween on slow devices (so it's always visible) 

i am using it in my current game without any problems.. 

 

actually i am using just the necessary code - not the plugin..  if you need something - just tell me

Share this post


Link to post
Share on other sites

well ... here it is..

create: function () {   game.add.existing(cover); // add the cover for the transition effect as early as possible    //other creation stuff here      cover.bringToTop();  // bring the cover for the stateTransition to top   game.time.events.add(0, fadeIn);  // start the fade out of the cover and therefore the fade in of the current state}
function fadeOut(target){    texture = new PIXI.RenderTexture(game.width, game.height, game.renderer);    matrix = new PIXI.Matrix();    matrix.translate(-game.camera.x, -game.camera.y);    texture.render(game.world, matrix);    cover = new Phaser.Sprite(game, 0, 0, texture);    cover.fixedToCamera = true;    cover.anchor.setTo(0.5,0.5);    cover.cameraOffset.x = game.width / 2;    cover.cameraOffset.y = game.height / 2;    game.state.start(''+target+''); }function fadeIn() {    if (!cover) {return;} // catch a very rare error where the cover is not created for some reason    tween1 = this.game.add.tween(cover).to({alpha: 0},  1000,Phaser.Easing.Exponential.InOut, true);    tween2 = this.game.add.tween(cover.scale).to({ x: 1.5,  y: 1.5 },  1000,Phaser.Easing.Exponential.InOut, true);    tween2.onComplete.addOnce(destroyCover, this);}function destroyCover() {    cover&&cover.destroy();    cover = null;    texture&&texture.destroy();    texture = null;}

so to change from one state to another (or to start a state when pressing a button) i use

fadeOut('somestate');

this creates the rendertexture and the "cover" and starts the given state..

the state then adds the existing "cover" (onTop) and starts the cover-zoom-fade Tween...   thats it.

i start the tween through a game.time.event because that way it waits for the new state creation process to finish - otherwise the tween would run between those creation processes and probably lag or not show at all..

Share this post


Link to post
Share on other sites

Thanks for the post.

 

I have a small flickering effect when the create function add the cover on the game.

We can prevent this flickering effect by adding the cover before state creation: in the init() state function.
 
So we can move the line below:
game.add.existing(cover); // add the cover for the transition effect as early as possible

to the init function:

init: function () {    game.add.existing(cover); // add the cover for the transition effect as early as possible}

Just for other people information, the code below could not work depending on when we create our display objects (keep in mind groups order).

We need to have the cover at the top, so it depends on your layers order.

cover.bringToTop();

If I have some time I'll post an updated version of the plugin in order to give everyone a working copy ;-)

Share this post


Link to post
Share on other sites

Ok, so the plugin function _draw looks like this code:

/* Draw the world state */function _draw(state) {var texture;var matrix;/* Pause the game at first */this.game.paused = true;/* If there's a sprite there, destroy it */if (this._cover) {this._cover.destroy();}/* If there's a state as a parameter change the state and do the dew */if (state) {texture = new PIXI.RenderTexture(game.width, game.height, game.renderer);matrix = new PIXI.Matrix();matrix.translate(-game.camera.x, -game.camera.y);texture.render(game.world, matrix);var _init = this.game.state.states[state]['init'];var _create = this.game.state.states[state]['create'];var _this = this;this._cover = new Phaser.Sprite(game, 0, 0, texture);this._cover.fixedToCamera = true;this._cover.anchor.setTo(0.5);//Instead of x/y we need to set the cameraOffset point */this._cover.cameraOffset.x = this.game.width / 2;this._cover.cameraOffset.y = this.game.height / 2;this.game.state.states[state]['init'] = function() {_init.call(_this.game.state.states[state]);_this.game.add.existing(_this._cover);};this.game.state.states[state]['create'] = function() {_create.call(_this.game.state.states[state]);_animateCover.call(_this);};this.game.state.start(state);}/* Resume the game */this.game.paused = false;}

I just added the init function call and your previously code with PIXI texture.

If anyone can test it on his own game. Sounds good on my side.

Share this post


Link to post
Share on other sites

interesting..  i can't see any flickering in my game but moving the cover to init sounds like a good idea nevertheless..  :)   

 

btw.  i have no idea why the game is paused in the plugin..  do you?   i tried several ways to accomplish the zoom/fade effect and game.pause didn't do anything good ..   

Share this post


Link to post
Share on other sites

I think it depends on your purposes. I made my own version because I need a specific behavior.

 

For the texture, I saw yesterday this code seems to do the same things as yours:

 

texture = new PIXI.RenderTexture(game.width, game.height, game.renderer);//matrix = new PIXI.Matrix();//matrix.translate(-game.camera.x, -game.camera.y);texture.render(game.world/*, matrix*/);

So I'm asking if it's necessary to add the matrix? Maybe I'm wrong?

Share this post


Link to post
Share on other sites

for a game world where the world is as big as the camera view and you are not moving the camera focus nor scaling your game world at some point (and maybe then - in the scaled mode - trigger the transition) - the matrix is not necessary.. 

in every other (more complex) game it's definitely necessary :)  i can't really describe what it does without those lines..  lets say the cover position is in no way predictable...

Share this post


Link to post
Share on other sites

For anyone using Phaser 2.2, the stage manager is no longer throwing a WebGL error in this version. The stage was still being drawn to the renderTexture upside down, but changing to draw the game world instead works as expected ( Thanks @valueerror for finding this previously ).

 

I've created a pull request for the author here:

 

https://github.com/cristianbote/phaser-state-transition/pull/8

 

If anyone wants to use my fork in the meantime, it's here:

 

https://github.com/nickryall/phaser-state-transition/tree/phaser-2.2-fix

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.