haxepunk/tweens/motion/LinearPath.hx
package haxepunk.tweens.motion;
import haxepunk.utils.Ease.EaseFunction;
import haxepunk.math.Vector2;
/**
* Determines linear motion along a set of points.
*/
class LinearPath extends Motion
{
/**
* Starts moving along the path.
* @param duration Duration of the movement.
* @param ease Optional easer function.
*/
public function setMotion(duration:Float, ?ease:EaseFunction)
{
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:Float, ?ease:EaseFunction)
{
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:Float = 0, y:Float = 0)
{
if (_last != null)
{
distance += Math.sqrt((x - _last.x) * (x - _last.x) + (y - _last.y) * (y - _last.y));
_pointD[_points.length] = distance;
}
_points[_points.length] = _last = new Vector2(x, y);
}
/**
* Gets a point on the path.
* @param index Index of the point.
* @return The Point object.
*/
public function getPoint(index:Int = 0):Vector2
{
if (_points.length == 0)
throw "No points have been added to the path yet.";
return _points[index % _points.length];
}
/** @private Starts the Tween. */
@:dox(hide)
override public function start()
{
_index = 0;
super.start();
}
/** @private Updates the Tween. */
@:dox(hide)
override function updateInternal()
{
if (_index < _points.length - 1)
{
while (_t > _pointT[_index + 1]) _index++;
}
var td:Float = _pointT[_index],
tt:Float = _pointT[_index + 1] - td;
td = (_t - td) / tt;
_prevPoint = _points[_index];
_nextPoint = _points[_index + 1];
x = _prevPoint.x + (_nextPoint.x - _prevPoint.x) * td;
y = _prevPoint.y + (_nextPoint.y - _prevPoint.y) * td;
}
/** @private Updates the path, preparing it for motion. */
function updatePath()
{
if (_points.length < 2)
throw "A LinearPath must have at least 2 points to operate.";
if (_pointD.length == _pointT.length)
return;
// evaluate t for each point
var i:Int = -1;
while (++i < _points.length)
_pointT[i] = _pointD[i] / distance;
}
/**
* The full length of the path.
*/
public var distance(default, null):Float = 0;
/**
* How many points are on the path.
*/
public var pointCount(get, never):Float;
function get_pointCount():Float return _points.length;
// Path information.
var _points:Array<Vector2> = [];
var _pointD:Array<Float> = [0];
var _pointT:Array<Float> = [0];
var _speed:Float = 0;
var _index:Int = 0;
// Line information.
var _last:Vector2;
var _prevPoint:Vector2;
var _nextPoint:Vector2;
}