* properties to either of the above.
* * {Function} [complete] Function called on animation completion.
* * {Function} [step] Function called after each step of the animation.
+ * @param {Float} [now] Time (ms) to use as the start-time. If omitted, the
+ * current time is used.
*/
- animate : function animate(duration, props, options) {
+ animate : function animate(duration, props, options, now) {
var A = new Animation(this, duration, props, options);
if ( A.options.queue && this.animActive.length )
this.animQueue.push(A);
else
- this.animActive.push(A.start(NOW)); // XXX: Need another way to pass NOW in
+ this.animActive.push(A.start(now || new Date().getTime()));
return this;
},
'init' : function(cooldown, isReady){
this.cooldown = cooldown; // ms
this.ready = isReady || true;
- this.last = new Date().getTime();
+ this.elapsed = (this.isReady ? this.cooldown : 0);
},
- 'activate' : function(now){
- now = now || new Date().getTime();
+ 'activate' : function(){
if ( this.ready ) {
- this.ready = false;
- this.last = now;
+ this.ready = false;
+ this.elapsed = 0;
return true;
}
return false;
},
- 'update' : function(now){
+ 'tick' : function(elapsed){
if (this.ready) return true;
- now = now || new Date().getTime();
- if ( (this.last+this.cooldown) <= now )
+ this.elapsed += elapsed || 0;
+ if (this.elapsed >= this.cooldown)
this.ready = true;
return this.ready;
},
- 'setCooldown' : function(cooldown, now){
+ 'setCooldown' : function(cooldown){
this.cooldown = cooldown;
- return this.update(now);
+ return this.tick();
},
- 'ratio' : function(now){
- now = now || new Date().getTime();
- if ( this.update(now) )
- return 1.0;
- else
- return now / (this.last+this.cooldown);
+ 'ratio' : function(){
+ return Math.min(1.0, this.elapsed / this.cooldown);
}
});
// times : null, // Last `samples` frame durations
- init : function init(target, framerate, samples){
+ /**
+ * @param framerate Target number of frames per second.
+ * @param [target] Object to decorate with start, stop, reset methods.
+ * @param [dilation=1] Number of real milliseconds that must elapse for 1
+ * perceived millisecond to elapse.
+ * @param [samples=33] Number of frames to track for effective fps
+ */
+ init : function init(framerate, target, dilation, samples){
Emitter.init.call(this, target);
decorate.call(this, target);
- this.tick = this.tick.bind(this);
+
+ this.tick = this.tick.bind(this);
this.decorate = decorate.bind(this);
- this.framerate = framerate;
+ this.framerate = framerate;
this.targetTime = 1000 / framerate;
- this.samples = samples || NUM_SAMPLES;
+ this.samples = samples || NUM_SAMPLES;
+ this.dilation = dilation || 1.0;
this.reset();
},
var lastTick = this.now;
this.now = new Date().getTime();
this.elapsed = this.now - lastTick;
+ this.perceived = this.elapsed/this.dilation;
clearTimeout(this.timer);
this.timer = null;
this.fire('tick', this, {
- now : this.now,
- elapsed : this.elapsed,
- ticks : ++this.ticks
+ 'now' : this.now,
+ 'elapsed' : this.perceived,
+ 'ticks' : ++this.ticks
});
var tFrame = this.tFrame = new Date().getTime() - this.now;
, defaults =
exports['defaults'] = {
+ game : {
+ timeDilation : 1.0,
+ gameoverDelay : 1000
+ },
ui : {
createGridCanvas : 1,
createGridTable : 0,
* @param {Number} start Starting diameter value.
* @param {Number} end Ending diameter value.
* @param {Number} duration Duration (ms) of the animation.
+ * @param {Float} [now] Time (ms) to use as the start-time. If omitted, the
+ * current time is used.
*/
- init : function initExplosion(start, end, duration){
+ init : function initExplosion(start, end, duration, now){
start = 0.5 * start;
end = 0.5 * end;
+ now = now || new Date().getTime();
Circle.init.call(this, start);
- this.animate(duration, {'radius':end}, { 'complete':this.remove.bind(this) });
+ this.animate(duration, { 'radius':end },
+ { 'complete':this.remove.bind(this) }, now);
var prev = this
, options = { 'step':this.updateRing }
;
prev = new Circle(ringStart)
.fill(color)
- .animate(duration, { 'radius':ringEnd }, options)
+ .animate(duration, { 'radius':ringEnd }, options, now)
.appendTo(prev);
}, this);
},
, EventLoop = require('ezl/loop').EventLoop
, Circle = require('ezl/shape').Circle
-, config = require('tanks/config')
+, config = require('tanks/config').values
, map = require('tanks/map')
, thing = require('tanks/thing')
, Grid = require('tanks/ui/grid').Grid
Game =
exports['Game'] =
Y.subclass('Game', {
- overlayPathmap : false,
+ overlayPathmap : config.pathing.overlayPathmap,
+ overlayAIPaths : config.pathing.overlayAIPaths,
+ timeDilation : config.game.timeDilation,
+ gameoverDelay : config.game.gameoverDelay,
gameover : false,
- gameoverDelay : 1000,
-
init : function initGame(viewport){
this.animations = new Y.YArray();
this.viewport = $(viewport || GRID_ELEMENT);
- this.loop = new EventLoop(this, FRAME_RATE);
+ this.loop = new EventLoop(FRAME_RATE, this, this.timeDilation);
this.root =
this.grid =
this.root.draw();
this.pathmap.removeOverlay(this.viewport);
- if (config.values.pathing.overlayPathmap)
+ if (this.overlayPathmap)
this.pathmap.overlay(this.viewport);
},
SECONDTH = ELAPSED / 1000;
SQUARETH = REF_SIZE * SECONDTH
- if (!tanks.config.values.pathing.overlayAIPaths)
+ if (!this.overlayAIPaths)
this.pathmap.hidePaths();
- this.active.invoke('updateCooldowns', NOW);
+ this.active.invoke('updateCooldowns', ELAPSED, NOW);
this.active.invoke('act');
this.animations = this.animations.filter(this.tickAnimations, this);
var dur = ex.timeBase + ex.timeInc*end;
start = ex.start * start;
end = ex.end * end;
- this.game.addAnimation(new Explosion(start, end, dur).position(x,y));
+ this.game.addAnimation(new Explosion(start, end, dur, NOW).position(x,y));
},
render : function render(parent){
remove : function remove(){
if (this.shape) this.shape.remove();
- // if (this.game) this.game.killUnit(this);
return this;
},
this._ai = Y(this.ai);
},
- updateCooldowns : function updateCooldowns(){
- this._cooldowns.invoke('update', NOW);
- this._ai.invoke('update', NOW);
+ updateCooldowns : function updateCooldowns(elapsed, now){
+ this._cooldowns.invoke('tick', elapsed, now);
+ this._ai.invoke('tick', elapsed, now);
return this;
},