AS3 Cubic Bezier Looping Lines

Posted: February 5th, 2010 | Author: Zack | Filed under: ActionScript 3, Experimental | Tags: , , | View Comments

Cubic Bezier Looping Lines

For this experiment I took some code I had written for a recent project and repuprosed it in a more artistic and abstract manner. The idea is basically to loop for a specified distance and create points, which are later connected into a continuous cubic bezier line. Here is the code:

public function createLoopingLine(distance:Number):void
{
    var points:Array = [];
    var currentDistance:Number = 0;
    var step:int = 50;
    var xDis:Number = 0;
    var yDis:Number = stage.stageHeight * .5;
    var iterations:int = Math.round(distance / step);
    var wasLastLoop:Boolean = true;
    var loopSize:Number;
   
    // push start point
    points.push(new Point(xDis, yDis));
   
    // loop through and create random looping points to span total distance
    for(var i:Number = 0; i < iterations; i++)
    {
        // if last segment of line was a loop, make it straight
        if(!wasLastLoop)
        {
            if(Math.random() > .5)
            {
                // loop up
                loopSize = randomNum(70, 200);
                // left point of loop
                points.push(new Point(xDis + (loopSize * .5), yDis - (loopSize * .5)));
                // top point of loop
                points.push(new Point(xDis, yDis - loopSize));
                // right point of loop
                points.push(new Point(xDis - (loopSize * .5), yDis - (loopSize * .5)));
                // bottom point of loop, origin point
                points.push(new Point(xDis, yDis));
            }
            else
            {
                // loop down
                loopSize = randomNum(-70, -200);
                // left point of loop
                points.push(new Point(xDis - (loopSize * .5), yDis - (loopSize * .5)));
                // top point of loop
                points.push(new Point(xDis, yDis - loopSize));
                // right point of loop
                points.push(new Point(xDis + (loopSize * .5), yDis - (loopSize * .5)));
                // bottom point of loop, origin point
                points.push(new Point(xDis, yDis));
            }
            // last points were a loop
            wasLastLoop = true;
        }
        else
        {
            // continue to step through
            xDis = currentDistance + 100;
            points.push(new Point(xDis, yDis + randomNum(-100, 100)));
            wasLastLoop = false;
        }
        // add to distance traveled
        currentDistance = xDis;
    }
    // push end point
    points.push(new Point(currentDistance+200, stage.stageHeight * .5));
   
    // create loop container
    var lineContainer:Sprite = new Sprite();
    addChild(lineContainer);
   
    // pass container and points
    curveThroughPoints(lineContainer, points, .5, .5);
}

The calculations to create the control points between the distance values generated in the loop above is based heavily on Andy Woodruff’s CubicBezier class. I just have added some strong typing and optimized some of the loops. To learn more about Andy’s CubicBezier class, visit http://www.cartogrammar.com/blog/continuous-curves-with-actionscript-3/. After the cubic control points are created, we loop through the distance points and create BezierSegments objects. The BezierSegment class takes four parameters, the start point, two control points, and the end point. For more on BezierSegment visit http://help.adobe.com/en_US/AS3LCR/Flash_10.0/fl/motion/BezierSegment.html. The segment is then looped through and “stamps” are added on each step.

var stamp:Sprite;
var thisPoint:Point;
var nextPoint:Point;               
var bezier:BezierSegment;

for (i = 0; i < lastPt - 1; i++)
{
    // create a BezierSegment from point, following point, and 2 control points generated above
    bezier = new BezierSegment(p[i], controlPts[i][1], controlPts[i + 1][0], p[i + 1]);
   
    for (var t = .01; t < 1.01; t += .15)
    {
        // get point to position stamp
        thisPoint = bezier.getValue(t);
        // get next point, this is used to calculate rotation
        nextPoint = bezier.getValue(t + .15);
       
        // position stamp and set rotation
        stamp = new Stamp()
        stamp.x = thisPoint.x,
        stamp.y = thisPoint.y;
        stamp.rotation = Math.round(Math.atan2(nextPoint.y - thisPoint.y, nextPoint.x - thisPoint.x) * (180 / Math.PI));
       
        // add the stamp to the container
        container.addChild(stamp);
    }
}

The stamps are library sprites. These are interchangeable with whatever you like. Some really interesting designs and patterns can be made. Here are some more renders I made by playing with graphics within the stamp sprite:

Cubic Bezier Looping Lines

Cubic Bezier Looping Lines

Cubic Bezier Looping Lines

Cubic Bezier Looping Lines

Note: The BezierSegment class is within the fl.motion package, which exists for Flash, you will not find this packge in the Flex SDK as of the time of this post.

Stay tuned, I have more planned for this experiment to evolve into. In the meantime, enjoy the source!

SOURCE FILES


  • http://www.nolithius.com Ebyan Alvarez-Buylla

    When playing with the source, I noticed that very small z values give hard corners (probably not what you want with a bezier class, but it still looks cool!).

    Also, if removing the z clamp on line 122, passing a z value of 1.5 to 2 causes concave squares that also look kind of nice!.

    I noticed on line 118, you’re clamping z down to .5 if below 0, was that intentional?

    Nice work!

  • http://www.nolithius.com Ebyan Alvarez-Buylla

    When playing with the source, I noticed that very small z values give hard corners (probably not what you want with a bezier class, but it still looks cool!).

    Also, if removing the z clamp on line 122, passing a z value of 1.5 to 2 causes concave squares that also look kind of nice!.

    I noticed on line 118, you’re clamping z down to .5 if below 0, was that intentional?

    Nice work!

  • Zack

    Yes, playing with those values can give you some interesting effects, for example, the second to last image in the post.

    The z value is set to .5 if it’s below 0 just to keep it “natural”. I haven’t actually tried setting it in the negative yet.

    You can probably get a lot more interesting effects by playing with these values more in conjunction with the “stamp” sprites. If you get some cool results I’d love to see them!

  • Zack

    Yes, playing with those values can give you some interesting effects, for example, the second to last image in the post.

    The z value is set to .5 if it’s below 0 just to keep it “natural”. I haven’t actually tried setting it in the negative yet.

    You can probably get a lot more interesting effects by playing with these values more in conjunction with the “stamp” sprites. If you get some cool results I’d love to see them!

blog comments powered by Disqus