AS3 Cubic Bezier Looping Lines
Posted: February 5th, 2010 | Author: Zack | Filed under: ActionScript 3, Experimental | Tags: ActionScript 3, bezier, generative art | View Comments
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:
{
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 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:




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!