Sign in to follow this  
Yehuda Katz

proper loading in progress

Recommended Posts

Hello,

I cannot manage to make Phaser continue updating stage while I am doing something in background. In particular, I noticed that to generate stage I need 2-4 seconds (resources are loaded but generation itself takes this time). So I decided to add loading by default withing create() method and call actual stage creation asynchronously by calling it in setTimeout(function() {}, 0). However, Phaser freezes tween animation:

var sprite = this.add.sprite(100, 100, 'loading');
this.game.add.tween(sprite.scale).to({x: 1.5, y: 1.5}, 500, Phaser.Easing.Linear.None, true, 0, -1, true);

setTimeout(function(that) {
  var time_now = (new Date()).getTime();
  while ((new Date()).getTime() - time_now < 2000) {}
  sprite.visible = false;
}, 0, this);

I attached two short files, one is with while loop (to simulate some work) and dot is not animating, the second one is without while loop and visible = false statement

var sprite = this.add.sprite(100, 100, 'loading');
this.game.add.tween(sprite.scale).to({x: 1.5, y: 1.5}, 500, Phaser.Easing.Linear.None, true, 0, -1, true);

setTimeout(function(that) {
  var time_now = (new Date()).getTime();
  // while ((new Date()).getTime() - time_now < 2000) {}
  // sprite.visible = false;
}, 0, this);

If that's not a way to do what I want to do then how can I show animation while I am preparing stage?

no animation.gif

animation.gif

Share this post


Link to post
Share on other sites

So seems like Phaser stops rendering once CPU is in use (even in parallel thread):

var sprite = this.add.sprite(100, 100, 'loading');
this.game.add.tween(sprite.scale).to({x: 1.5, y: 1.5}, 500, Phaser.Easing.Linear.None, true, 0, -1, true);

setTimeout(function() {
  var time_now = (new Date()).getTime();
  while ((new Date()).getTime() - time_now < 2000) {}
}, 3000);

This example demonstrates how animation works fine after stage is created but once while loop starts in 3 second, the tween animation freezes.

Is there any way to force Phaser redraw stage? I can add that code in between lines which generate stage.

Share this post


Link to post
Share on other sites

JS is single-threaded (without web workers), so if you're running a task uninterrupted for 2–4 seconds, the browser will stop sending Phaser animation frames until idle time is available again.

I think you'd have to either batch your work so it fits into consecutive update intervals (~10ms each), or call game.updateLogic and game.updateRender manually.

Share this post


Link to post
Share on other sites

@samme thanks, I tried to call both those methods within while loop but it did not help. I also came to the same conclusion yesterday regarding splitting job into chunks and executing them with 10ms delay, so Phaser will have time to update the canvas.

What do you think about idea to convert function into string then pass it to function which will split it into chunks and executes them with 10ms delay each? Or may be there is some easier way to stop execution to tell system do jobs in other queues for 10ms? I even tried https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function but without much success + Safari did not implemented it yet

Share this post


Link to post
Share on other sites

@samme basically you solved problem with calling each chunk with certain delay by using update() method. The only problem is, how to split work into chunks. Such code will be very difficult to debug or analyse. Of course any stage generation would have loops which theoretically could be exported to such update() method... but those loops should be executed in certain order. The second loop cannot start until first one is not finished... and what if there are dozens of loops. I am thinking to create some kind of queue where each chunk of loop is submitted as anonymous function. So old style code:

for (var i in my_custom_buttons) {
  // create images, assign events etc
}

should be converted into something like

create() {
  var queue = [];
  for (var i in my_custom_buttons) {
    queue.push(function() {
      // create images, assign events etc
    })  
  }
}

update() {
  queue.splice(0, 1)[0]();
}

as for queue, in update method we can do queue.pop() and execute given chunk of the code. What do you think?

Share this post


Link to post
Share on other sites

@samme you may ignore my previous post. I tried it in my app and it's not as smooth as it looks. You should not only put code within chunks but also wait for the whole queue to be completed, before you can execute the main code. It's just like loading content before starting the stage in Phaser.

How Phaser manages to show loading screen before anything? When I added Phaser's native loading code and then execute my heavy code, Phaser still managed to display loading screen first! How can I do the same? If I can do the same then I can cover screen with membrane so user knows that button was clicked, input was accepted by app and user needs to wait 1-2 sec.

Thanks

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

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.