Basic Circle Drawing ActionScript
Do you know how to draw a circle with ActionScript code? It’s a handy thing to know. You can use it to draw pie charts, equilateral polygons, analog clock faces… you can even use it to script motion. If you use Flash for any type of drawing purposes, knowing the math behind the circles (trigonometry) can be very helpful. In the simplest of terms, drawing a circle can be as easy as counting from 0 to 1.
When drawing a circle, you must place your pen on the paper somewhere to start. Before you do this, you are at point 0 (zero), meaning you haven’t drawn anything. And then once you finish drawing your circle you will have reached your goal. You will have drawn 1 (one) circle. So to draw a circle, you must go through the points between 0 and 1.
To get from 0 to 1 will take a certain number of steps. How many is up to you. The number of steps determines the number of sides your “polygon” will have. “Polygon?” you say, “I thought we were drawing a circle.” Well sure, theoretically. Circles have an infinite number of points around their circumference, but we don’t have an infinite amount of time to plot out every possible point, so we’re going to approximate our circle by using a finite set of points. When we connect these points we will have a regular polygon. For this example I’m going to take 100 steps from 0 to 1 which will make a 100 sided polygon that is going to look a LOT like a circle.
So far we’ve established that drawing a circle requires you to start at 0, go through “some steps”, and then you’ll end up with 1 circle. But what are the steps?
This is where the magic of computers comes in handy. Trigonometry is a big hairy spider with numbers and fangs. It’s scary, hard and not for the timid. But if you’re brave enough to try taming it, you’ll come to understand it’s just a spider and easily squashed. Whether you battle the Trigonometry monster now or later is up to you but you need to understand this simple concept, all points on the circle’s edge are measured from the center of the circle. If you’re at the center of a big clock face and want to get to 3 o’clock you need to take a few steps to the right of center (x). If you’re at the center of the clock and want to get to 12 o’clock you need to take a few steps up from center (y). If you’re at center and wanted to get to 1:30, you’d take a couple steps to the right then a couple steps up (no diagonal steps). That’s the least you need to know about Trigonometry to draw a circle.
So hopefully you understand that you need to know where the center of your circle is. For this example I’ll pick a center X 0f 250 and a center Y of 250. The next thing you need to know is the radius of your circle, or as in my previous example, the number of steps it takes to get from the center of the clock to 12 o’clock. For this example our circle will have a radius of 200 pixels.
Believe it or not, we now have enough information to start writing some code.
//
// As discussed above, All we need to know is
// the center of the circle, it's size and the
// number of sides we want to draw.
function drawCircle(centerX, centerY, radius, sides){
//
// Find a point for every "side" of the circle and
// draw a line to it.
for(var i=0; i<=sides; i++){
//
// Pick a point on the circle. The second
// point on a 100 sided circle will be
// point #2 out of 100 or point 2/100.
// The point can be represented as a ratio from 0 to 1.
var pointRatio = i/sides;
//
// Steps is the number of steps you have to take from
// the center to reach your point on the circumference.
// We'll use trigonometry to determine how many steps
// to take in each direction to get to this particular point.
var xSteps = magicTrigFunctionX(pointRatio);
var ySteps = magicTrigFunctionY(pointRatio);
//
// Once you know how many steps to take,
// You need to go to the center then take the right
// number of steps in each direction.
// The radius determines the size of every step taken.
var pointX = centerX + xSteps * radius;
var pointY = centerY + ySteps * radius;
//
// Now that you know where the point is,
// draw a line to it.
this.lineTo(pointX, pointY);
}
}
//
// Set a linestyle so we can see the circle.
lineStyle(0);
//
// Draw a 100 sided circle with a 200 pixel radius.
drawCircle(250, 250, 200, 100);
//
//
Now if you run the above code you’ll quickly see a problem. It doesn’t work. This is because the functions called “magicTrigFunctionX” or “magicTrigFunctionY” don’t exist. There are comparable functions (Math.cos and Math.sin), but they’re not quite magic enough for my liking. You see, back before there were computers, the eggheads needed something called “radians” to figure out how many steps it takes to get to each point on a circle. So to be nice, people used to convert their nice 0-to-1 ratios to radians (big ugly irrational numbers) so the eggheads would have an easier job and quit complaining so much.
But converting nice and neat 0-to-1-ratios to irrational numbers sounds complicated, is it? Not really, all you need to do is multiply your 0-to-1-ratio by 2 and then multiply it by Math.PI. Why 2? Why Math.PI? Just because it makes the eggheads job a little easier. But now we have computers and they don’t complain nearly as much as eggheads, so there’s no real reason to do this anymore, we’ll let the computer do it for us.
In the example code above I wrote:
var xSteps = magicTrigFunctionX(pointRatio);
var ySteps = magicTrigFunctionY(pointRatio);
//
But the eggheads want to see:
var xSteps = Math.cos(pointRatio*2*Math.PI);
var ySteps = Math.sin(pointRatio*2*Math.PI);
//
If you want to be a conformist you can use the code above and all will be fine. You’ll be using Flash’s native functions and the eggheads won’t laugh at you for using “magic” functions. If you’d like to make things a little easier, you might consider making some custom functions like this:
function magicTrigFunctionX (pointRatio){
return Math.cos(pointRatio*2*Math.PI);
}
function magicTrigFunctionY (pointRatio){
return Math.sin(pointRatio*2*Math.PI);
}
//
Adding the above functions to our previous code and removing all the comments gives us the following:
function magicTrigFunctionX (pointRatio){
return Math.cos(pointRatio*2*Math.PI);
}
function magicTrigFunctionY (pointRatio){
return Math.sin(pointRatio*2*Math.PI);
}
//
function drawCircle(centerX, centerY, radius, sides){
for(var i=0; i<=sides; i++){
var pointRatio = i/sides;
var xSteps = magicTrigFunctionX(pointRatio);
var ySteps = magicTrigFunctionY(pointRatio);
var pointX = centerX + xSteps * radius;
var pointY = centerY + ySteps * radius;
this.lineTo(pointX, pointY);
}
}
//
lineStyle(0);
//
drawCircle(250, 250, 200, 100);
//
Which produces the following SWF file:
As you can see, there is a slight flaw with the code in that it starts drawing our circle from the default position of (0, 0) then draws a line all the way over to our first point on the circle. To fix this we need to modify the code to start off by moving the pen to the first point on the circle and then drawing the lines to all of the other points.
function magicTrigFunctionX (pointRatio){
return Math.cos(pointRatio*2*Math.PI);
}
function magicTrigFunctionY (pointRatio){
return Math.sin(pointRatio*2*Math.PI);
}
//
function drawCircle(centerX, centerY, radius, sides){
//
// Move the pen to the first point on the circle.
this.moveTo(centerX + radius, centerY);
//
for(var i=0; i<=sides; i++){
var pointRatio = i/sides;
var xSteps = magicTrigFunctionX(pointRatio);
var ySteps = magicTrigFunctionY(pointRatio);
var pointX = centerX + xSteps * radius;
var pointY = centerY + ySteps * radius;
this.lineTo(pointX, pointY);
}
}
//
lineStyle(0);
//
drawCircle(250, 250, 200, 100);
//
Running the above code produces the following SWF file:
So there you have it. One circle drawn with ActionScript. And all you had to do was count from 0 to 1 (sort of) 😉 .
Update: The next tutorial in this series is How to Draw an Arc with ActionScript.
[…] drawing an oval or ellipse is about as easy as drawing a circle with ActionScript. When drawing a circle you only need one measurement for the circle’s radius but when drawing an oval […]
@Joel, You’re welcome. Glad to have helped.
Awesome! Finaly I understand this, though I’m just 14 years old and from Sweden. Thanks, very well explained!
Sorry to persist with this question. If I use the matrix, boxMat, above, to manually generate the pixel coordinates from the logical coordinates and then do the drawing then everything is fine – i get a smoothly joined antialiased curve. That is, if i don’t change the Canvas transform matrix to boxMat ( i don’t have the line ‘pnl.transform.matrix = boxMat;’) but only use boxMat to calculate my pixel coordinates from my logical coordinates using boxMat.transformPoint() and then draw with those pixel coordinates all is fine.
But I thought the whole point of
pnl.transform.matrix = boxMat;
was to avoid the manual conversion from logical to pixel. It doesn’t seem to work that way.
[…] If you’ve read my previous Circle Drawing Tutorial you understand that Flash approximates circles and arcs by connecting a series of straight lines. […]
Hi,
If I set a custom scale that is not close to the default scale and then use your routine ( or the one using curveto ) to draw the circle( or arc) the outcome looks all crooked and bad.
I am mapping the height or width( whichever is smaller) to 10 units ( -5 to 5 ). And setting the origin at the center. I am drawing on a Flex Canvas component called ‘pnl’.
var h:int = pnl.height;
var cscale:Number = (w < h)?w/10.0:h/10.0;
var boxMat:Matrix = new Matrix();
boxMat.createBox(cscale,-cscale,0,w*0.5,h*0.5);
pnl.transform.matrix = boxMat;
I then draw a circle or arc of radius, say, 4.0 with 100 sides and it comes out all wiggly and crooked.
Any suggestions for solving this problem? Thanks in advance.
obj.lineStyle(.25, color);
obj.beginFill(color, 100);
obj.moveTo(X+r, Y)
for (i=0; i<100; i++) {
ang = i * (2*Math.PI/100)
xpos = r*Math.cos(ang)+X;
ypos = r*Math.sin(ang)+Y;
obj.lineTo(xpos, ypos)
}
obj.endFill();
}
The above code is a bit more useful. Less functions and code, and therefore less space. Also you can specify the color and object and it fills the circle.
hello. i need help. i need to draw the sin and cos functions. can anyone help me? telling me the exact steps. thank you
Thank you for providing this code example
[…] task until you realize that this is a problem that you solve every time you draw a circle. In my How to Draw a Circle tutorial I discussed a Magic Trig Function which just happens to be the perfect mechanism for driving the […]
Thank you for providing this code example. I’m pretty weak in math and finding good examples like this makes my coding life a lot easier. I agree with you about not underestimating the usefulness of this type of code. I’m using your example not to draw circles but to move sprites in curves, arcs, and spirals. The sprites are dancers and your example will help me define and smooth the choreography.
Thanks
You’re welcome Tatlar, and thanks for the feedback.
Thanks for this tutorial – I reinterpreted it into Javascript for my needs. Very clearly written.
Thank you Mr. N. 🙂
Though the DrawCircle function may no longer be necessary in AS3, the code within it is still relevant and quite useful. As I said at the beginning of the article, you can use it to do a lot more than just draw circles (Tantalizing Tendril).
Nice post Mr P.
It may be worth clarifying this as being for AS2 and lower. AS3 has graphics.drawCircle() – thank goodness :]