Skip to content

Commit 9760468

Browse files
committed
Detect "spiralling" due to CPU falling behind.
Permanently skip frames when spiralling occurs.
1 parent 6468285 commit 9760468

1 file changed

Lines changed: 47 additions & 8 deletions

File tree

src/core/Game.js

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,18 @@ Phaser.Game = function (width, height, renderer, parent, state, transparent, ant
270270
*/
271271
this._deltaTime = 0;
272272

273+
/**
274+
* @property {number} _lastCount - remember how many 'catch-up' iterations were used on the logicUpdate last frame
275+
* @private
276+
*/
277+
this._lastCount = 0;
278+
279+
/**
280+
* @property {number} _spiralling - if the 'catch-up' iterations are spiralling out of control, this counter is incremented
281+
* @private
282+
*/
283+
this._spiralling = 0;
284+
273285

274286
this._width = 800;
275287
this._height = 600;
@@ -653,16 +665,43 @@ Phaser.Game.prototype = {
653665

654666
this.time.update(time);
655667

656-
// accumulate time until the _slowStep threshold is met or exceeded
657-
this._deltaTime += Math.max(Math.min(1000, this.time.elapsed), 0);
668+
// if the logic time is spiralling upwards, skip a frame entirely
669+
if (this._spiralling > 1)
670+
{
671+
// TODO: cause an event to warn the program that this CPU can't keep up at the current desiredFps rate
658672

659-
// call the game update logic multiple times if necessary to "catch up" with dropped frames
660-
var step = 1000.0 / this.time.desiredFps;
661-
var slowStep = this.time.slowMotion * step;
662-
while(this._deltaTime >= slowStep)
673+
// reset the _deltaTime accumulator which will cause all pending dropped frames to be permanently skipped
674+
this._deltaTime = 0;
675+
this._spiralling = 0;
676+
}
677+
else
663678
{
664-
this._deltaTime -= slowStep;
665-
this.updateLogic(1.0 / this.time.desiredFps);
679+
// step size taking into account the slow motion speed
680+
var slowStep = this.time.slowMotion * 1000.0 / this.time.desiredFps;
681+
682+
// accumulate time until the slowStep threshold is met or exceeded
683+
this._deltaTime += Math.max(Math.min(1000, this.time.elapsed), 0);
684+
685+
// call the game update logic multiple times if necessary to "catch up" with dropped frames
686+
var count = 0;
687+
while(this._deltaTime >= slowStep)
688+
{
689+
this._deltaTime -= slowStep;
690+
this.updateLogic(1.0 / this.time.desiredFps);
691+
count++;
692+
}
693+
694+
// detect spiralling (if the catch-up loop isn't fast enough, the number of iterations will increase constantly)
695+
if (count > this._lastCount)
696+
{
697+
this._spiralling++;
698+
}
699+
else if (count < this._lastCount)
700+
{
701+
// looks like it caught up successfully, reset the spiral alert counter
702+
this._spiralling = 0;
703+
}
704+
this._lastCount = count;
666705
}
667706

668707
// call the game render update exactly once every frame

0 commit comments

Comments
 (0)