@@ -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