package net.flashpunk.tweens.motion { import flash.geom.Point; /** * 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) { // avoid zero-length path segments if (x == _last.x && y == _last.y) return; _distance += Math.sqrt((x - _last.x) * (x - _last.x) + (y - _last.y) * (y - _last.y)); _pointD[_points.length] = _distance; } else { this.x = x; this.y = y; } _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 (_points.length == 1) { x = _points[0].x; y = _points[0].y; return; } 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 < 1) throw new Error("A LinearPath must have at least one point."); if (_pointD.length == _pointT.length) return; // evaluate t for each point 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; } // Path information. /** @private */ private var _points:Vector. = new Vector.; /** @private */ private var _pointD:Vector. = new Vector.; /** @private */ private var _pointT:Vector. = new Vector.; /** @private */ private var _distance:Number = 0; /** @private */ private var _speed:Number = 0; /** @private */ private var _index:uint = 0; // Line information. /** @private */ private var _last:Point; /** @private */ private var _prev:Point; /** @private */ private var _next:Point; } }