Fps handling on gainFocus

Hi guys,

I’ve got the following situation: If my game looses its focus (by for example switching the window) it is able to automatically set itself in a pause state (which is already implemented in SimpleApplication.

Now my problem is this part:
[java] @Override
public void update() {
super.update(); // makes sure to execute AppTasks
if (speed == 0 || paused) {
return;
}

    float tpf = timer.getTimePerFrame() * speed;[/java] 

So while the game is paused nothing is updated. But if it regains the focus the timer will return an extremely high tpf. Theoretically that is okay because the next frame took a long time because of the pause state. The problem is: this tpf-value is not usable in any time-based method. for example if you move a car depending on the tpf-value the car will take an extremely huge jump forward (and maybe crashs into a school. Hell! Nobody wants that! ^^).

Also automatically moved cameras could end in an obscure position, bullets could fly through the targets without hitting them and so on.

Why not put the tpf above the pause-statement?

[java] @Override
public void update() {
super.update(); // makes sure to execute AppTasks

    float tpf = timer.getTimePerFrame() * speed;

    if (speed == 0 || paused) {
        return;
    }

[/java]

Another way could be this:

[java]
@Override
public void gainFocus()
{
_regainFocus = true;
super.gainFocus();
}

private boolean _regainFocus = false;

@Override
public void update()
{
	if(_regainFocus){
		_regainFocus = false;
		getTimer().reset();
	}
	
	super.update();
}

[/java]

What do you think?

Regards,

ceiphren

1 Like

I always noticed odds things happening when I unpaused using this same method, things flying around at 400mph, this is probably why :slight_smile: good catch

The tpf should really only be used for on screen animation and not game simulation. There is a bit of an oddity in the way pause works as it’s not a game pause but a rendering pause… and JME makes no distinction between the two. We sometimes add stuff because it’s convenient for simple apps but then will generally completely fall down for any app of reasonable complexity. To me, the worst part is that the current state is the least useful as it leaves you not even being able to render an “I’m Paused Right Now” screen because rendering has been halted.

I recommend to anyone wanting to implement a proper pause that a) they override the default pause to simply reduce the frame rate to a crawl by bleeding off processing with a sleep(), and b) keep their own timer for game/simulation objects that is not based on tpf. Though I guess it’s possible to pause the JME timer and still play frames and bleed off CPU… things tend to get freaked out about 0 tpf.

It’s also a sore spot with me that this handling isn’t just an app state… because I’d really like to be able to turn off or replace the default crappy pause support without having to override methods… but here we are. I’ve been trying to think of a way to fix it without breaking backwards compatibility but nothing has popped into my head yet.

This topic happened to hit a nerve because I once again find myself having to override default behavior to make one of my own apps behave sensibly. :slight_smile:

@ceiphren said: Hi guys,

I’ve got the following situation: If my game looses its focus (by for example switching the window) it is able to automatically set itself in a pause state (which is already implemented in SimpleApplication.

Now my problem is this part:
[java] @Override
public void update() {
super.update(); // makes sure to execute AppTasks
if (speed == 0 || paused) {
return;
}

    float tpf = timer.getTimePerFrame() * speed;[/java] 

So while the game is paused nothing is updated. But if it regains the focus the timer will return an extremely high tpf. Theoretically that is okay because the next frame took a long time because of the pause state. The problem is: this tpf-value is not usable in any time-based method. for example if you move a car depending on the tpf-value the car will take an extremely huge jump forward (and maybe crashs into a school. Hell! Nobody wants that! ^^).

Also automatically moved cameras could end in an obscure position, bullets could fly through the targets without hitting them and so on.

Why not put the tpf above the pause-statement?

To answer that question in particular… it doesn’t matter since tpf is local and the pause causes the whole method to return anyway. Where you calculate it doesn’t matter because it will just be thrown away anyway.

@pspeed: Okay but how about my second suggestion?

And I don’t understand the problem about the current fps value. Can you give me a case?

hmm I use tpf for everything

This issue would also explain, why debugging in jME can be a nightmare sometimes

@ceiphren said: @pspeed: Okay but how about my second suggestion?

And I don’t understand the problem about the current fps value. Can you give me a case?

Doesn’t the second case mean that time will go backwards?

You’ll have to forgive me because I have trouble understanding code while the forum is still so screwed up. Seriously thinking of taking a long vacation from the forums.

@pspeed: ah you’re right. I didn’t see that 'cause the only thing I need is the tpf, not the elapsed time since start.

@wezrule: Yeah, with this little workaround debugging should be much easier but it also resets the timer every time. The problem I currently can imagine is network communication where the client has to respond all the time (which would make this solution senseless if you have a multiplayer at all)

The idea of a “Paused” screen is what I think about when I think of the problems of using render time and game time as the same thing. Alternately, the game is smart enough to know it’s paused and stop updating… but then there was no reason for default pause behavior in the first place.

Personally, I think there should be a way for app states to be notified about lost focus and then do whatever they want with that information.

@ceiphren said: @pspeed: ah you're right. I didn't see that 'cause the only thing I need is the tpf, not the elapsed time since start.

@wezrule: Yeah, with this little workaround debugging should be much easier but it also resets the timer every time. The problem I currently can imagine is network communication where the client has to respond all the time (which would make this solution senseless if you have a multiplayer at all)

For the network you have a own thread anyway usually, so the keepalives can be send regardles of the renderer pause.
But yes the pause on lost focus makes debugging sometimes quite worse, at the other side they are nice for simple singleplayer games (most of the time at least)