topical media & game development

talk show tell print

mobile-query-three-plugins-minecraft-tquery.animation.js / js



  tQuery.registerStatic('createAnimation', function(opts){
          return new tQuery.Animation(opts);
  });
  
  
////////////////////////////////////////////////////////////////////////////

// Constructor //
////////////////////////////////////////////////////////////////////////////

handle an animation @name tQuery.Animation @class

  
  tQuery.registerStatic('Animation', function(opts){
          opts        = this._opts        = tQuery.extend(opts, {
                  world        : tQuery.world
          })
          this._keyframes                = new Array;
          this._totalTime                = null;
          this._onUpdate                = null;
          this._onCapture                = function(position){};
          this._initialPos        = {};
          this._propertyTweens        = {};
  });
  
  
Destructor

  
  tQuery.Animation.prototype.destroy        = function(){
          this.stop();
  };        
  
  
////////////////////////////////////////////////////////////////////////////

// setup //
////////////////////////////////////////////////////////////////////////////


parameter: {Number} duration the duration of this keyframe validity in seconds
parameter: {Object} position list of properties involved in the animations

  
  tQuery.Animation.prototype.pushKeyframe        = function(duration, position){
          this._keyframes.push({
                  duration        : duration,
                  position        : position
          });
          return this;        // for chained API
  };
  
  
Set the Update callback
parameter: {function} fn the update callback

  
  tQuery.Animation.prototype.onUpdate        = function(fn){
          this._onUpdate        = fn
          return this;        // for chained API
  }
  
  
Set the Capture callback
parameter: {function} fn the update callback

  
  tQuery.Animation.prototype.onCapture        = function(fn){
          this._onCapture        = fn
          return this;        // for chained API
  }
  
  
Set propertyTweens
parameter: {function} fn the update callback

  
  tQuery.Animation.prototype.propertyTweens        = function(propertyTweens){
          this._propertyTweens        = propertyTweens;
          return this;        // for chained API
  }
  
  
get the total animation duration
returns: {Number} the duration of the whole animation

  
  tQuery.Animation.prototype.duration        = function(){
          if( this._keyframes.length === 0 )        return 0;
          var lastKeyframe        = this._keyframes[this._keyframes.length - 1];
          return lastKeyframe._endTime;
  };
  
  
////////////////////////////////////////////////////////////////////////////

// interpolation //
////////////////////////////////////////////////////////////////////////////

build a interpolated position
parameter: {Number} age amount of seconds since the animation started

  
  tQuery.Animation.prototype._buildPosition        = function(age){
          // compute the deltatime
          var delta        = age % this.duration();
          // find baseFrame based on delta
          for(var frameIdx = 0; frameIdx < this._keyframes.length; frameIdx++){
                  var baseFrame        = this._keyframes[frameIdx];
                  if( delta <  baseFrame._startTime )        continue;
                  if( delta >= baseFrame._endTime )        continue;
                  break;
          }
          // sanity check - the baseFrame has to be known
          console.assert( frameIdx !== this._keyframes.length );
          // compute some variables
          var timeOffset        = delta - baseFrame._startTime;
          var timePercent        = timeOffset / baseFrame.duration;
          var nextFrame        = this._keyframes[ (frameIdx+1) % this._keyframes.length ];
  
          //console.log("delta", delta)
          //console.log("frameIdx", frameIdx)
          //console.log("timeOffset", timeOffset)
          //console.log("timePercent", timePercent)
  
          var basePosition= baseFrame.position;
          var nextPosition= nextFrame.position;
  
          // zero this._initialPos if age > baseFrame.duration - it wont be usefull anymore
          if( age > baseFrame.duration && this._initialPos )        this._initialPos= null;
          // if frameIdx === 0 and there is a this._initialPos, use it as basePosition
          if( frameIdx === 0 && this._initialPos )        basePosition        = this._initialPos;
          
          // compute the result based on the linear interpolation between the two frames based on time offset within the frame
          var result        = {};
          for( var property in baseFrame.position ){
                  // check the property exists
                  console.assert( nextPosition[property]        !== undefined );
                  console.assert( basePosition[property]        !== undefined );
                  // linear interpolation between the values
                  var baseValue        = basePosition[property];
                  var nextValue        = nextPosition[property];
                  // define propertyTween for this property - default to linear interpolation
                  var propertyTween        = this._propertyTweens[property] || function(baseValue, nextValue, timePercent){
                          return (1-timePercent) * baseValue + timePercent * nextValue;
                  }
                  // compute the actual result
                  result[property]= propertyTween(baseValue, nextValue, timePercent);
          }
          // return the result
          return result;
  };
  
  
////////////////////////////////////////////////////////////////////////////

// //
////////////////////////////////////////////////////////////////////////////

Start the animation

  
  tQuery.Animation.prototype.start        = function(){
          // update _startTime and _endTime
          this._totalTime        = 0;
          this._keyframes.forEach(function(keyframe){
                  keyframe._startTime        = this._totalTime;
                  this._totalTime                += keyframe.duration;
                  keyframe._endTime        = this._totalTime;
          }.bind(this));
  
          // get this._initialPos from this._onCapture()
          // - the initial position is the position when the animation started.
          // - it will be used as basePosition during the first keyframe of the animation
          // - it is optional. the user may not define it
          this._initialPos= tQuery.extend({}, this._keyframes[0].position)
          this._onCapture(this._initialPos);
  
          // init the loop callback
          var startDate        = Date.now()/1000;
          var duration        = this.duration();
          this._loopCb        = this._opts.world.loop().hook(function(){
                  var age                = Date.now()/1000 - startDate;
                  var position        = this._buildPosition(age)
                  this._onUpdate(position)
          }.bind(this));
  }
  
  
test if the animation is running or not
returns: {boolean} return true if the animation is running, false otherwise

  
  tQuery.Animation.prototype.isRunning        = function(){
          return this._loopCb        ? true : false;
  };
  
  
Stop the animation

  
  tQuery.Animation.prototype.stop        = function(){
          this._loopCb        && this._opts.world.loop().unhook(this._loopCb);
          this._loopCb        = null;
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.