StageXL
StageXL copied to clipboard
Any way to pause the render loop if nothing is happening?
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.
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:
- Auto - you will see continuous rendering
- Once - the stage will be rendered once at the next render event
- 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!
When trying to automate this behaviour, I found it best to extend RenderLoop
, overriding advanceTime
and setting the StageRenderMode
according to some conditions, before calling the super function:
- check if
Juggler
has something going on viahasAnimatables
– if true, go forAUTO
, elseONCE
- check if any
ENTER_FRAME
listeners are present – if true, go forAUTO
, elseONCE
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
StageRenderMode
toONCE
in 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 toONCE
- 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 :-)
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.
@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, 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.
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.
@bp74 @kevmoo I did a PR with a first attempt, would love your thoughts on it.
@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).
I will work on this feature over the weekend. The code will be very similar to the one fromNils, i will keep you posted.
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.
Anything new? Starting to realize this is a big deal for battery drain.
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.
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.