Rope Class

by bradsedito
♥0 | Line 90 | Modified 2011-09-06 12:42:14 | MIT License
play

ActionScript3 source code

/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fg4P
 */






package
{

    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.display.MovieClip;
    import flash.display.Sprite;

    public class Rope extends Sprite
    {

        public var gravity:Number                                         = 0;
        public var elastics:Number                                         = 0.2;
        public var friction:Number                                         = 0.1;
        private var startPoint:Object;

        private var endPoint:Object;
 private var segments:Number                                     = 0;
 

        public function Rope(segments:Number, startx:Number, starty:Number, endx:Number, endy:Number) 

        {

            

            this.initCord(segments, startx, starty, endx, endy);

            

        }

        

        /**

        * ...

        * Update the startPoint object. Use this if you need to update the points of the rope without creating a new rope instance

        * @param x: change the startPoint.x value

        * @param y: change the startPoint.y value

        */

        

        public function setStartPoint(x:Number, y:Number):void 

        {

                this.startPoint.x = x || 0;

                this.startPoint.y = y || 0;

        }

        

        /**

        * ...

        * Update the endPoint object. Use this if you need to update the points of the rope without creating a new rope instance

        * @param x: change the endPoint.x value

        * @param y: change the endPoint.y value

        */



        public function setEndPoint(x:Number, y:Number):void

        {

                this.endPoint.x = x || 0;

                this.endPoint.y = y || 0;

        }

        

        public function get _segments():Number 

        {

                return this.segments;

        }

        

        

        /**

        * ...

        * Redraw function. This is the function that you use to update the cord on a loop

        * @param cord: the Sprite object where the rope is located

        */

        

        public function reDraw(cord:Sprite):void 

        {

            

            // this is the core of the rope functionality

            // this function creates a series of steps to be drawn on the sprite with the curveTo method

            

            

            var segments:Number                 = (this.segments*2+1);

            var elastics:Number                 = this.elastics;

            var friction:Number                    = 1-this.friction;

            var gravity:Number                     = this.gravity / segments;

            

            // the pointer is moved to the startPoint.x and startPoint.y

            cord.graphics.moveTo(this.startPoint.x, this.startPoint.y);

            

            // the current_point object is created based on the next points to draw

            var current_point:Object = this.startPoint.next_point;

            

            // a loop runs all those points

            while (current_point.next_point) 

            {

                

                // target variables are created. this variables assign how much length is left for the startPoint meet the endPoint

                var targetx:Number                 = (current_point.prev_point.x+current_point.next_point.x)/2;

                var targety:Number                 = (current_point.prev_point.y + current_point.next_point.y) / 2;

                

                // the step values are increased based on how much length is needed. here also the elastic multiplier is applied for the X and Y axis and the gravity is applied to the Y axis

                current_point.x_step             += (targetx-current_point.x)*elastics;

                current_point.y_step             += (targety - current_point.y) * elastics + gravity;

                

                // the step vales are multiplied by the friction (easing)

                current_point.x_step             *= friction;

                current_point.y_step             *= friction;

                

                // the current point object increases with the finalized step values. all done to be drawn on the sprite

                current_point.x                 += current_point.x_step;

                current_point.y                 += current_point.y_step;

                

                // the current point refreshes to start a new point

                current_point                     = current_point.next_point;

                    

            }

            

            if (cord) 

            {

                

                var control_point:Object         = this.startPoint.next_point;

                

                // a loop runs all points

                while (control_point.next_point) 

                {

                    

                    // draws a quadratic curve based on the next points to go

                    cord.graphics.curveTo(control_point.x, control_point.y, (control_point.next_point.x+control_point.x)/2, (control_point.next_point.y+control_point.y)/2);

                    control_point = control_point.next_point;

                    

                }

                

                // when the curve is finished, a line is drawn to reach the control points

                cord.graphics.lineTo(control_point.x, control_point.y);

                

            }

            

        }

        

        /**

        * ...

        * @private

        * This initializes the cord engine. Creates the segments, start and end point objects

        */

       

        private function initCord(segments:Number, startx:Number, starty:Number, endx:Number, endy:Number):void

        {

                if (!segments || segments < 1) 

                {

                    

                    segments = 1;

                    

                }

                
                this.segments                     = segments;
                this.startPoint                 = {x:startx || 0, y:starty || 0};

                //

                var x_step:Number                 = (endx-startx)/segments || 0;
                var y_step:Number                 = (endy - starty) / segments || 0;
                var current_point:Object        = this.startPoint;

                while ((--segments) > 0) 
                {

                    current_point                 = this.addPoint(current_point, x_step, y_step);            
                }
                
                current_point                     = this.addPoint(current_point, x_step, y_step);        
                this.endPoint                     = {x:endx || 0, y:endy || 0, prev_point:current_point};

                current_point.next_point         = this.endPoint;

        }

        private function addPoint(prev_point:Object, x_step:Number, y_step:Number):Object 
        { 
            var new_point:Object                 = {y_step:0, x_step:0, prev_point:prev_point, y:prev_point.y+y_step, x:prev_point.x+x_step};
            prev_point.next_point                 = new_point;

            return new_point;

        }
    }
}