Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to pause the render loop if nothing is happening? #263

Open
kevmoo opened this issue Feb 7, 2017 · 12 comments
Open

Any way to pause the render loop if nothing is happening? #263

kevmoo opened this issue Feb 7, 2017 · 12 comments

Comments

@kevmoo
Copy link
Contributor

kevmoo commented Feb 7, 2017

In my crazy outdated bot_web retained silly - https://github.com/kevmoo/bot_web.dart/tree/master/lib/src/bot_retained

I kept track of dirty information and I wouldn't render frames unless something changed.

Any way to do this with StageXL? I see that the render events keep pumping, even if nothing is going on.

@bp74
Copy link
Owner

bp74 commented Feb 8, 2017

Hi,

Yes you can do this! Please take a look at the StageRenderMode enum.

You can set the stage.renderMode property to one of the following values:

  1. Auto - you will see continuous rendering
  2. Once - the stage will be rendered once at the next render event
  3. Stop - the stage will not be rendered

If you change something on the Stage, you can set the "Once" value and you will get an updated stage. After this render event the property will automatically change it's value to "Stop". So every time you want the stage to be rendered you set it back to "Once".

I wonder why i have no example for this, i will add this to some of the examples soon!

@nilsdoehring
Copy link
Collaborator

When trying to automate this behaviour, I found it best to extend RenderLoop, overriding advanceTime and setting the StageRenderModeaccording to some conditions, before calling the super function:

  • check if Juggler has something going on via hasAnimatables – if true, go for AUTO, else ONCE
  • check if any ENTER_FRAMElisteners are present – if true, go for AUTO, else ONCE

This should suffice for a lot of use cases.

For more complex applications, I haven't yet been able to find an elegant solution for:

  • MOUSE_MOVE, MOUSE_WHEEL, TOUCH_MOVE – if you have an implementation not relying on ENTER_FRAME or Juggler, it is necessary to set StageRenderModeto ONCEin the listeners of your implementation.
  • RESIZE – if you employ a liquid/responsive layout, you probably want this event to activate AUTO, but it is sometimes tricky to find the best point in time when to switch back to ONCE
  • Shaders – If your shader requires a full frame rate, you need to set to AUTO
  • I think there was more, but I can't remember

If I had the time, I would go for a centralized RenderModeManager (singleton?), which ensures that all of the above plays well with each other – we don't want accidental resets to ONCE. Alternatively, we could nag @bp74 to add this to Juggler, as opt-in functionality :-)

@kevmoo
Copy link
Contributor Author

kevmoo commented Feb 8, 2017

I'd love to have this be auto-magic, @nilsdoehring – I've implemented it before.

No clue how easy here. I just don't like tabs burning CPU when nothing is moving. Makes the mobile users sad.

@nilsdoehring
Copy link
Collaborator

nilsdoehring commented Feb 8, 2017

@kevmoo, would you be able to provide any pointers, preferably in ActionScript? (because easiest to port)

I'm motivated to revisit the case, especially since my implementation is faulty, but if disabled, would melt down the CPU in the example linked above. Will follow up, here.

@kevmoo
Copy link
Contributor Author

kevmoo commented Feb 8, 2017

@kevmoo, would you be able to provide any pointers, preferably in ActionScript? (because easiest to port)

@nilsdoehring sadly, no. Not sure if there is a way to do it generically.

One improvement: it'd be nice to just have a requestFrame method on stage. If called before drawing (and a frame is already requested) – no-op. If called during a frame, make sure a frame is scheduled.

@bp74
Copy link
Owner

bp74 commented Feb 8, 2017

The starling framework in v2.0 implemented auto-magic idle mode :) But you won't get it for free, basically every change to one of the DisplayObject or DisplayObjectContainer properties and several other trigger will mark the display tree as dirty. It's nice for applications where most of the time nothing changes, but it hurts performance for games where each frame is different.

@nilsdoehring
Copy link
Collaborator

@bp74 @kevmoo I did a PR with a first attempt, would love your thoughts on it.

@nilsdoehring
Copy link
Collaborator

@kevmoo After exchange with @bp74 in the PR (thanks!), here's a gist of a RenderLoop that works with the current StageXL API (1.1.0).

@bp74
Copy link
Owner

bp74 commented Feb 15, 2017

I will work on this feature over the weekend. The code will be very similar to the one fromNils, i will keep you posted.

@audioMirror
Copy link

I implemented this by using a Once and Stop stage modes. Invalidating an object in my GUI framework causes the Stop to go to a Once. I have to keep track of Canvas Resizes as well.

This is a feature one wants on a GUI framework (like I use), but would be expensive to set up in a game framework.

@unicomp21
Copy link

Anything new? Starting to realize this is a big deal for battery drain.

@unicomp21
Copy link

Could it be simple as just checking whether or not the juggler has work to do? Then it's on the dev, if he wants to save battery, to make sure animation stops after a period of idle time from user.

@bp74
Copy link
Owner

bp74 commented Oct 21, 2017

There is a very simple trick. First you set stage.RenderMode to StageRenderMode.AUTO_INVALID which will only render the Stage if someone called the stage.invalidate() method. Next, you derive your own Juggler from the standard Juggler and override the advanceTime method. In this method, check if the hasAnimatable property is true, and in this case call stage.invalidate().

If all your animations use an instace of your Juggler, everything should work as expected.

This would be easy to implement in StageXL itself. But i don't want to make the stagexl.animation library (where Juggler exists) dependent on the stagexl.display library (where Stage exists). I was thinking about some magic to make this work, but never figured out a way that makes me happy. Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants