0

I am having trouble with the delta/ elapsed time.

When the window is blurred the loop pauses correctly.

If you wait a few seconds and click back onto the window (focus), the elapsed time starts at a higher number and then resets back to 0.

How do I stop the elapsed time from increasing when the window is blurred? This higher number affects my animation and makes it run too fast until the delta is correct again.

I have setup an example loop. You can see what I mean in the console: Example

if (window.requestAnimationFrame !== undefined) {
    window.requestAnimFrame = (function () {
        'use strict';

        return window.requestAnimationFrame ||
               window.webkitRequestAnimationFrame ||
               window.oRequestAnimationFrame ||
               window.mozRequestAnimationFrame ||
               function (callback) {
                    window.setTimeout(callback, 1000 / 60); //Should be 60 FPS
               };
    }());
}

(function () {
    'use strict';

    var elapsed,
        isPaused = false,
        lastTime = 0,
        loop,
        setElapsed,
        startTime = 0,
        update;

    //Set the elapsed time
    setElapsed = function () {
        startTime = Date.now();
        elapsed = startTime - lastTime; //Calculate the elapsed time since the last frame. Dividing by 1000 turns it to seconds
        lastTime = startTime;
    };

    update = function () {
        //Update the animation etc.
        console.log('animation');
    };

    loop = function () {
        setElapsed();
        update(elapsed);    

        console.log('elapsed: ' + elapsed);

        requestAnimFrame(function () {
            if (isPaused === false) {
                loop();
            } 
        }); //Re-loop constantly using callback window.setTimeout(callback, 1000 / 60); //Should be 60 FPS

    };

    //When the window blurs, pause it
    window.onblur = function () {
        isPaused = true; //Pause the game
    };

    //When the window is in focus, resume it
    window.onfocus = function () {
        isPaused = false;
        loop(); //Re-init the game
    };

    loop();

}());

Thanks

Paddy
  • 1,175
  • 1
  • 14
  • 23

1 Answers1

1

elapsed assignment (inside setElapsed function) should use lastTime only when the latter is non-zero. Otherwise it should be set to 0 (which means the 1st call).

Furthermore you have to reset lastTime to 0 when onblur event occurs.

setElapsed = function () {
    startTime = Date.now();
    elapsed = lastTime? startTime - lastTime : 0;
    lastTime = startTime;
};
...
window.onblur = function () {
    isPaused = true; // Pause the game
    lastTime = 0; // reset lastTime
};
hindmost
  • 7,125
  • 3
  • 27
  • 39
  • That is an excellent solution and it works. Thanks a lot. I appreciate it. – Paddy Apr 04 '15 at 18:58
  • @Paddy You could upvote this answer as well if it solve your problem – hindmost Apr 04 '15 at 19:09
  • An improved version of your answer would use the timestamp parameter passed into requestAnimationFrame to implement an elapsed time. ;-) – markE Apr 04 '15 at 19:18
  • @markE `requestAnimationFrame` has fixed [signature](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame). Maybe you meant `callback` function? – hindmost Apr 04 '15 at 19:24
  • @hindmost, Nope, I mean `timestamp`. See the first example in your link. Cheers! ;-) – markE Apr 04 '15 at 19:29
  • Upvoted. What is the timestamp method as well. I like having multiple solutions when learning. – Paddy Apr 04 '15 at 20:02
  • @Paddy Native version of `requestAnimationFrame` passes timestamp of the current time (in milliseconds) to your callback function (`loop()`) which you can use in your calculations (see [here](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) for details). However I don't think it might significantly simplify your code. – hindmost Apr 05 '15 at 08:59