From ca0f80bfd69bc78457888ffc035f11098ecff6e5 Mon Sep 17 00:00:00 2001 From: dsc Date: Mon, 13 Dec 2010 06:47:02 -0800 Subject: [PATCH] Adds time dilation for testing. --- src/ezl/layer.cjs | 6 ++++-- src/ezl/loop/cooldown.cjs | 27 +++++++++++---------------- src/ezl/loop/eventloop.cjs | 24 +++++++++++++++++------- src/tanks/config.cjs | 4 ++++ src/tanks/fx/explosion.cjs | 10 +++++++--- src/tanks/game.cjs | 17 +++++++++-------- src/tanks/thing/bullet.cjs | 2 +- src/tanks/thing/thing.cjs | 7 +++---- 8 files changed, 56 insertions(+), 41 deletions(-) diff --git a/src/ezl/layer.cjs b/src/ezl/layer.cjs index bda0d81..6857efb 100644 --- a/src/ezl/layer.cjs +++ b/src/ezl/layer.cjs @@ -551,13 +551,15 @@ Y.subclass('Layer', { * 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; }, diff --git a/src/ezl/loop/cooldown.cjs b/src/ezl/loop/cooldown.cjs index ae6961c..3c30c07 100644 --- a/src/ezl/loop/cooldown.cjs +++ b/src/ezl/loop/cooldown.cjs @@ -7,40 +7,35 @@ Y.subclass('Cooldown', { '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); } }); diff --git a/src/ezl/loop/eventloop.cjs b/src/ezl/loop/eventloop.cjs index f363926..aaccdd5 100644 --- a/src/ezl/loop/eventloop.cjs +++ b/src/ezl/loop/eventloop.cjs @@ -21,15 +21,24 @@ methods = { // 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(); }, @@ -79,14 +88,15 @@ methods = { 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; diff --git a/src/tanks/config.cjs b/src/tanks/config.cjs index 5d10793..c7f2989 100644 --- a/src/tanks/config.cjs +++ b/src/tanks/config.cjs @@ -3,6 +3,10 @@ var Y = require('Y').Y , defaults = exports['defaults'] = { + game : { + timeDilation : 1.0, + gameoverDelay : 1000 + }, ui : { createGridCanvas : 1, createGridTable : 0, diff --git a/src/tanks/fx/explosion.cjs b/src/tanks/fx/explosion.cjs index 5014f4a..d8069ea 100644 --- a/src/tanks/fx/explosion.cjs +++ b/src/tanks/fx/explosion.cjs @@ -15,13 +15,17 @@ Circle.subclass('Explosion', { * @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 } @@ -35,7 +39,7 @@ Circle.subclass('Explosion', { ; prev = new Circle(ringStart) .fill(color) - .animate(duration, { 'radius':ringEnd }, options) + .animate(duration, { 'radius':ringEnd }, options, now) .appendTo(prev); }, this); }, diff --git a/src/tanks/game.cjs b/src/tanks/game.cjs index 6cf740c..4d0787d 100644 --- a/src/tanks/game.cjs +++ b/src/tanks/game.cjs @@ -6,7 +6,7 @@ var Y = require('Y').Y , 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 @@ -19,11 +19,12 @@ var Y = require('Y').Y 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){ @@ -36,7 +37,7 @@ Y.subclass('Game', { 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 = @@ -74,7 +75,7 @@ Y.subclass('Game', { this.root.draw(); this.pathmap.removeOverlay(this.viewport); - if (config.values.pathing.overlayPathmap) + if (this.overlayPathmap) this.pathmap.overlay(this.viewport); }, @@ -91,10 +92,10 @@ Y.subclass('Game', { 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); diff --git a/src/tanks/thing/bullet.cjs b/src/tanks/thing/bullet.cjs index e6f3992..2f2b155 100644 --- a/src/tanks/thing/bullet.cjs +++ b/src/tanks/thing/bullet.cjs @@ -125,7 +125,7 @@ Thing.subclass('Bullet', { 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){ diff --git a/src/tanks/thing/thing.cjs b/src/tanks/thing/thing.cjs index efd59a6..56b5f95 100644 --- a/src/tanks/thing/thing.cjs +++ b/src/tanks/thing/thing.cjs @@ -83,7 +83,6 @@ new evt.Class('Thing', { remove : function remove(){ if (this.shape) this.shape.remove(); - // if (this.game) this.game.killUnit(this); return this; }, @@ -103,9 +102,9 @@ new evt.Class('Thing', { 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; }, -- 1.7.0.4