Starling fps & requestAnimationFrame

Hi all!

I’m a little confused. If I create a simple project using the Starling library, which merely
displays Starling’s built-in fps counter (Starling.current.showStats) and don’t set a framerate
in project.xml, I get around 60fps in FireFox & Chrome.
As soon as I specify a framerate of say 40, like:

<window background="#ffffff" fps="40" />

all of a sudden the framerate seems to be capped at 30fps. This can be reproduced with the
StarlingDemo too.
Maybe someone knows what’s going on?

Also, some forum posts say we should set fps to 0 for HTML5 target to utilize requestAnimationFrame
but conceal what this actually means. As far as I can see this just sets the framerate to 1 and things
like Event.ENTER_FRAME are firing once a second. What is this good for?

The current behavior of <window fps="" /> on HTML5 is that >= 60 will use requestAnimationFrame, but something less will use a JavaScript timer. requestAnimationFrame is highly recommended, but your logic must be frame independent, as a 144hz monitor may run at 144 FPS, for example.

The current behavior of fps = 0 is to set the frame rate to 1 FPS, but perhaps this is not ideal. I’m open to discussing the ideal expected behavior? (We can fix our documentation to match whatever we choose is best)

Sorry singmajesty, I’m not sure I can follow.
If I set the framerate to 0 for the HTML5 target (thus utilizing requestAnimationFrame as the docs
say), I should throw away all ENTER_FRAME events and replace 'em by maybe TimerEvent.TIMER
to fire every say 16 ms to get my 60 fps? If I do so, when will requestAnimationFrame be called?
I don’t have any influence I guess?

Here is how it works now:

1.) <window fps="0" /> means 1 FPS, using a JavaScript timer
2.) <window fps="30" /> means approximately 30 FPS, using a JavaScript timer
3.) <window fps="60" /> or greater (or undefined) means requestAnimationFrame, so 60+ FPS and smooth

requestAnimationFrame is basically what you want on HTML5, unless you are building an application and not a game :slight_smile:

Thanks for taking the time but one question remains: What actually triggers
requestAnimationFrame?
Say I have a typical game scenario where I want to update all on-screen objects
after handling input, collission detection,…
Usually (using a fixed framerate of maybe 40fps) I would have done it via ENTER_FRAME.

Now if I set the framerate to a fixed value of >=60 using ENTER_FRAME would be
useless since I don’t know what refresh rate the device is using.
So I have to use TimerEvent.TIMER which has to fire every 25ms to get my 40fps and
basically means I’m using a JavaScript timer again. What is the benefit?

In addition to that I searched for some information about requestAnimationFrame and
found a code sample for a typical and simple use case:

var fps = 15;
function draw() {
    setTimeout(function() {
        requestAnimationFrame(draw);
        // Drawing code goes here
    }, 1000 / fps);
}

source

So the game update routine is called by a JavaScript timer and inside is a call to
requestAnimationFrame. But there’s no way to call it from OpenFL because OpenFL is
doing it for us behind the scenes! How does OpenFL decide when it’s time to call
requestAnimationFrame? How does it sync with my game update routine in case it’s
a timer?

It looks like I am wrong.

It used to work the way I described. It does use requestAnimationFrame, all the time

Feel free to take a look, if you think this should behave differently

So how does it work now? :slight_smile:
If I am converting a flash game with strict 60 fps logic, is it safe to set fps=“60”?

You would need to use an FPS of 59 or lower, currently, to try and use a vsync timer to approximate the value of your choice

Wouldn’t it be more sensible to change it from >= 60 to > 60 for people porting their Flash projects like me?

Many people use 60 FPS to mean “full speed,” OpenFL SWF animations remember the original frame rate and run at the original speed regardless of the stage frame rate, maybe there’s a way to do something similar with Starling or he DragonBones library, where do the animations come from?

Maybe a flag like use-that-slow-js-timer="true"? :slight_smile:

I don’t use any. The engine updates animated bitmaps every 3-4 frames… Do you think I can replace the main ENTER_FRAME event with a timer event?

How does it look currently if you try 59?

We tried 59, 40 and even 10, and looks like it has no effect on HTML5 target.
We did see the difference in Flash. In HTML we were able to change the frame rate with stage.frameRate.

You might need to do <window fps="59" /> or something similar in the project.xml, we might detect at compile time whether it’s going to use full requestAnimationFrame or not. I’d have to test to be sure if stage.frameRate properly crosses that threshold (between the full frame, or vsync approach)

So… I found this code in HTML5Window.hx:

setFrameRate: function(value) {
	if(this.parent.application != null) {
		if(value >= 60) {

and changed it to (value > 60) to allow strict 60 fps cap.
For my game it led to better smoothness than with (value >= 60) or fps=59 in project.xml.
I assume that is because most devices refresh at 60Hz.

So… I’d suggest toggling “full speed” for HTML5 (and maybe other targets) not at fps=60, but at fps=0, unless fps=0 is reserved for something else.

I think this is worth considering, though I believe that fps=0 is a special mode that’s supposed to not render at all, unless something changes on screen, or perhaps it just forces it to once every second or every 30 seconds? I would have to look again to know, probably once per frame, or never