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.
This commit is contained in:
Amadeus Demarzi 2015-02-06 15:28:26 -08:00
parent 5afed7e52b
commit 61536cb1f8
2 changed files with 35 additions and 7 deletions

View File

@ -68,7 +68,10 @@ Engine = Base.extend({
this.background.className += ' show'; this.background.className += ' show';
this.canvas.style.opacity = 1; 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) .wait(1000)
.then(function(){ .then(function(){
this.starGeneratorRate = 200; this.starGeneratorRate = 200;
@ -202,6 +205,13 @@ Engine = Base.extend({
this.now = Date.now() / 1000; this.now = Date.now() / 1000;
this.tick = Math.min(this.now - this.last, 0.017); 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 // Update all particles... may need to be optimized
for (p = 0; p < this.particles.length; p++) { for (p = 0; p < this.particles.length; p++) {
this.particles[p].update(this); this.particles[p].update(this);

View File

@ -1,12 +1,29 @@
(function(){ (function(){
var Chainable = function(){ var Chainable = function(engine){
this.engine = engine;
this._chain = []; this._chain = [];
this._updateTimer = this._updateTimer.bind(this);
this._cycle = this._cycle.bind(this); this._cycle = this._cycle.bind(this);
}; };
Chainable.prototype._running = false; 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(){ Chainable.prototype.start = function(){
if (this._running || !this._chain.length) { if (this._running || !this._chain.length) {
return this; return this;
@ -19,9 +36,8 @@ Chainable.prototype.reset = function(){
if (!this._running) { if (!this._running) {
return this; return this;
} }
clearTimeout(this._timer); this.resetTimer();
this._timer = null; this._timer = 0;
this._chain.length = 0;
this._running = false; this._running = false;
return this; return this;
}; };
@ -40,8 +56,10 @@ Chainable.prototype._cycle = function(){
return this._cycle(); return this._cycle();
} }
if (current.type === 'wait') { if (current.type === 'wait') {
clearTimeout(this._timer); this.resetTimer();
this._timer = setTimeout(this._cycle, current.time || 0); // Convert timer to seconds
this._timerMax = current.time / 1000;
this.engine.updateChainTimer = this._updateTimer;
current = null; current = null;
} }