From 61536cb1f8d3c49742967ed1b6003bdc6f21be46 Mon Sep 17 00:00:00 2001 From: Amadeus Demarzi Date: Fri, 6 Feb 2015 15:28:26 -0800 Subject: [PATCH] Attach Chainable timers to Engine render loop Previous to this commit, the Chainable class which is responsible for iterating on the sequence of events in the intro Terraform animation, was using setTimeout and thus could result in very messed up race conditions when triggering physics changes. This commit attaches the .wait timers to the Engine.render loop which should enable everything to stay in sync. --- .../source/assets/javascripts/app/Engine.js | 12 +++++++- .../assets/javascripts/lib/Chainable.js | 30 +++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/website/source/assets/javascripts/app/Engine.js b/website/source/assets/javascripts/app/Engine.js index a918be3b0..e89d61074 100644 --- a/website/source/assets/javascripts/app/Engine.js +++ b/website/source/assets/javascripts/app/Engine.js @@ -68,7 +68,10 @@ Engine = Base.extend({ this.background.className += ' show'; this.canvas.style.opacity = 1; - new Chainable() + // We have to pass the engine into Chainable to + // enable the timers to properly attach to the + // run/render loop + new Chainable(this) .wait(1000) .then(function(){ this.starGeneratorRate = 200; @@ -202,6 +205,13 @@ Engine = Base.extend({ this.now = Date.now() / 1000; this.tick = Math.min(this.now - this.last, 0.017); + // We must attach the chainable timer to the engine + // run/render loop or else things can get pretty + // out of wack + if (this.updateChainTimer) { + this.updateChainTimer(this.tick); + } + // Update all particles... may need to be optimized for (p = 0; p < this.particles.length; p++) { this.particles[p].update(this); diff --git a/website/source/assets/javascripts/lib/Chainable.js b/website/source/assets/javascripts/lib/Chainable.js index edb7f1757..dbe51dd1d 100644 --- a/website/source/assets/javascripts/lib/Chainable.js +++ b/website/source/assets/javascripts/lib/Chainable.js @@ -1,12 +1,29 @@ (function(){ -var Chainable = function(){ +var Chainable = function(engine){ + this.engine = engine; this._chain = []; + this._updateTimer = this._updateTimer.bind(this); this._cycle = this._cycle.bind(this); }; Chainable.prototype._running = false; +Chainable.prototype._updateTimer = function(tick){ + this._timer += tick; + if (this._timer >= this._timerMax) { + this.resetTimer(); + this._cycle(); + } +}; + +Chainable.prototype.resetTimer = function(){ + this.engine.updateChainTimer = undefined; + this._timer = 0; + this._timerMax = 0; + return this; +}; + Chainable.prototype.start = function(){ if (this._running || !this._chain.length) { return this; @@ -19,9 +36,8 @@ Chainable.prototype.reset = function(){ if (!this._running) { return this; } - clearTimeout(this._timer); - this._timer = null; - this._chain.length = 0; + this.resetTimer(); + this._timer = 0; this._running = false; return this; }; @@ -40,8 +56,10 @@ Chainable.prototype._cycle = function(){ return this._cycle(); } if (current.type === 'wait') { - clearTimeout(this._timer); - this._timer = setTimeout(this._cycle, current.time || 0); + this.resetTimer(); + // Convert timer to seconds + this._timerMax = current.time / 1000; + this.engine.updateChainTimer = this._updateTimer; current = null; }