package net.flashpunk.tweens.motion
{
import flash.geom.Point;
import net.flashpunk.FP;
/**
* Determines linear motion along a set of points.
*/
public class LinearPath extends Motion
{
/**
* Constructor.
* @param complete Optional completion callback.
* @param type Tween type.
*/
public function LinearPath(complete:Function = null, type:uint = 0)
{
super(0, complete, type, null);
_pointD[0] = _pointT[0] = 0;
}
/**
* Starts moving along the path.
* @param duration Duration of the movement.
* @param ease Optional easer function.
*/
public function setMotion(duration:Number, ease:Function = null):void
{
updatePath();
_target = duration;
_speed = _distance / duration;
_ease = ease;
start();
}
/**
* Starts moving along the path at the speed.
* @param speed Speed of the movement.
* @param ease Optional easer function.
*/
public function setMotionSpeed(speed:Number, ease:Function = null):void
{
updatePath();
_target = _distance / speed;
_speed = speed;
_ease = ease;
start();
}
/**
* Adds the point to the path.
* @param x X position.
* @param y Y position.
*/
public function addPoint(x:Number = 0, y:Number = 0):void
{
if (_last)
{
_distance += Math.sqrt((x - _last.x) * (x - _last.x) + (y - _last.y) * (y - _last.y));
_pointD[_points.length] = _distance;
}
_points[_points.length] = _last = new Point(x, y);
}
/**
* Gets a point on the path.
* @param index Index of the point.
* @return The Point object.
*/
public function getPoint(index:uint = 0):Point
{
if (!_points.length) throw new Error("No points have been added to the path yet.");
return _points[index % _points.length];
}
/** @private Starts the Tween. */
override public function start():void
{
_index = 0;
super.start();
}
/** @private Updates the Tween. */
override public function update():void
{
super.update();
if (_index < _points.length - 1)
{
while (_t > _pointT[_index + 1]) _index ++;
}
var td:Number = _pointT[_index],
tt:Number = _pointT[_index + 1] - td;
td = (_t - td) / tt;
_prev = _points[_index];
_next = _points[_index + 1];
x = _prev.x + (_next.x - _prev.x) * td;
y = _prev.y + (_next.y - _prev.y) * td;
}
/** @private Updates the path, preparing it for motion. */
private function updatePath():void
{
if (_points.length < 2) throw new Error("A LinearPath must have at least 2 points to operate.");
if (_pointD.length == _pointT.length) return;
var i:int = 0;
while (i < _points.length) _pointT[i] = _pointD[i ++] / _distance;
}
/**
* The full length of the path.
*/
public function get distance():Number { return _distance; }
/**
* How many points are on the path.
*/
public function get pointCount():Number { return _points.length; }
/** @private */ private var _points:Vector.<Point> = new Vector.<Point>;
/** @private */ private var _pointD:Vector.<Number> = new Vector.<Number>;
/** @private */ private var _pointT:Vector.<Number> = new Vector.<Number>;
/** @private */ private var _distance:Number = 0;
/** @private */ private var _speed:Number = 0;
/** @private */ private var _index:uint = 0;
/** @private */ private var _last:Point;
/** @private */ private var _prev:Point;
/** @private */ private var _next:Point;
}
}