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
Allow specifying fps on HTML platform #36
Conversation
Apologies for the major delay on this. But all of this is unnecessary. PlayN just emits a "frame" signal 60 times a second (or whatever the browser manages with requestAnimationFrame). The default implementation of It's true that your patch allows totally arbitrary frame times to be specified, but no one does that. Games render at 30fps or 60fps and that's pretty much it (or 90 if you're doing VR but I don't think anyone's doing VR with PlayN). So I'd rather keep things simple and just have games skip every other frame if they want a lower FPS. |
I disagree. What I found was that in Chrome if you skip a frame, it will still clear the framebuffer and thus render a black frame. But maybe I was testing wrong. |
You must have been testing wrong. protected void paintScene () {
viewSurf.saveTx();
viewSurf.begin();
viewSurf.clear(cred, cgreen, cblue, calpha);
try {
rootLayer.paint(viewSurf);
} finally {
viewSurf.end();
viewSurf.restoreTx();
}
}
private int frame = 0;
@Override public void paint (Clock clock) {
if (++frame % 2 == 0) super.paint(clock);
} However, I did just test that and discover that the LWJGL3 backend (when you're testing with Java) does flicker if you take this approach (or behave super weirdly if you skip an odd number of frames). That's because it double buffers and if you skip every other frame then you basically never render into one of the two buffers. To reduce the framerate on the Java backend, we actually have to provide a configuration setting so that we can tell LWJGL to wait two frames before swapping buffers and syncing (and you would not do the paint override that I described above). So if I did want to support 30 fps games, I'd probably provide an API that allowed you to specify the number of frames to wait before swapping buffers (like the API used by the Java backend). This would not allow you to specify an arbitrary FPS, but would allow you to halve, (or third, fourth, fifth, etc. but that would be pretty crazy) the framerate by requesting that paints happen every other frame. This ensures that the paints happen in line with the vsync which is usually necessary to avoid tearing (half of a frame showing up and half of an old frame). But if you are just halving the frame-rate on the HTML5 backend, then I'd do something like the following: public class MyGame extends SceneGame {
private final int frameSkip;
private int skippedFrames = 0;
public MyGame (Platform plat, int frameSkip) {
super(plat);
this.frameSkip = frameSkip;
}
@Override public void paint (Clock clock) {
if (skippedFrames < frameSkip) {
skippedFrames++;
} else {
super.paint(clock);
skippedFrames = 0;
}
}
} Then you can pass in a frameSkip of 1 from your HTML backend, and 0 from your Java backend, and you'll run at 30FPS in HTML and 60FPS in Java. |
You are right of course, it works in chrome afterall. One small note for future reference: it is a good idea to change the dt value of the Clock object passed to the paint Signal, to accomodate for skipped frames. |
While letting the browser control frame render times is a nicer solution, setting a lower fps manually results in your CPU not overheating if rendering is slower than 60 fps, which is ultimately pretty useful.