AS3 example Drawing graphics
<pageby nominor="false" comments="false"/>
Drawing Graphics
This example belongs to the AS3 Tutorials Novice and is part of our Actionscript 3 tutorial series.
You will learn about so-called Sprites. They define a small display area able to contain graphics and media content that you can reposition or manipulate later on.
Program
Copy and paste this code in a text file. Save that textfile as "FilledCircle.as". The name of the file *must* be the same as the name of the main class.
package { import flash.display.Sprite; public class FilledCircle extends Sprite { function FilledCircle():void { var circle:Sprite = new Sprite(); circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill(); addChild(circle); } } }
Walk Through
Okay, let's go through that program step by step to try and understand how this works.
---
package {
No string follows the word package. This means that we don't bother storing our code in independent regions. We have a single package.
---
import flash.display.Sprite;
The import statement is a consequence of the class organisation. Though we won't make use of classes in our very first programs, the thing is that the code that defines how Flash works and how elements are laid out on the screen is defined within a class-based organization. Each class does something very specific. There is one, for instance that contains all the code required for drawing graphics on the screen. This class is the Sprite class. And the Sprite class belongs to the display package which is itself part of the flash package.
Greatly simplified, what this means is ... we will need to play with Sprite objects (that is objects that can be drawn into) in this program, so please make all the code associated to Sprite objects available to my program.
---
public class FilledCircle extends Sprite {
This is a class definition. This corresponds to saying what follows is the code that defines FilledCircle objects and their behaviors. The extends part means that we want our FilledCircle object to inherit all properties of a Sprite object (more about this later).
---
function FilledCircle():void {
This is an instance constructor. When any part of the program tries to create an object of type FilledCircle, run this code. The best way to conceptualize this is initialization code every time a new object is being created.
---
var circle:Sprite = new Sprite();
What we do here is declare a variable called circle and have it hold the definition of a new Sprite Object. The reason we need to create one is because we want to draw something on the screen. We could draw directly on the screen.. But then we would loose any ability to manipulate the object later on. See it like the contrast between creating graphics on a blackboard and creating graphics with a sophisticated enough image editing software. If you draw a circle on a blackboard, then later on add some text, you might discover that you don't have room enough and you need to move the circle. On a blackboard, you can't. You have to restart from scratch. Erase a part or the totality of the content of the board and start drawing again. When you use an image editing software, if you come to discover that the circle was not drawn at the right location, you can select it and move it somewhere else on the screen without having to redraw it.
Well, that's what Sprites are about. They define a small display area able to contain graphics and media content that you can reposition or manipulate later on.
We mentioned that AS3 is a strongly typed object. Because of that we have to write var circle:Sprite = new Sprite() rather than var circle = new Sprite(). We create a variable called circle and we specify to the program that the type of information that this variable will hold is the definition of a Sprite object.
---
circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill();
This part draws a circle. It doesn't draw a circle directly on the screen. What it does is to draw a circle within a Sprite object. Because of that, each line starts with circle, the sprite object in which we want the graphics to be added. Then we grab the drawable area ("graphics") and we perform various drawing actions on it. beginFill specifies that we want to draw filled shapes. What follows is a color parameter. The value of "0xFF794B" is at first sight a bit strange. It defines a color in a format easy to manipulate for a computer. This is exactly the same hexadecimal format than used in HTML in case you are already familiar with it (0xFFFFFF stands for white, 0x000000 stands for black). Let's not spend too much time on this. Color code values can be obtained on this color code reference page at webmonkey.com. drawCircle draws a circle which has for center the point (50,50) (50 pixels from the left, 50 pixels from the top) and for radius 30 (30 pixels). endFill indicates that we have finished with drawing filled shapes.
---
addChild(circle);
Above we mentioned that we didn't draw directly on the screen. What we did was to draw onto a Sprite object. For the circle to appear on the screen, it is necessary to add the sprite object to the stage.
---
} } }
Any parenthesis or bracket that has been opened must be closed.
Variants
Try and change the position of the circle and its size. Change the color. Try to draw a bull's-eye.
Why not draw other shapes?
For a rectangle, use:
sprite.graphics.drawRect(x, y, width, height);
For an ellipse, use:
sprite.graphics.drawEllipse(x, y, width, height);
For a rounded rectangle, use:
sprite.graphics.drawRoundRect(x, y, width, height, ellipseWidth, ellipseHeight);
Gotchas
When you tried to create multiple shapes, did it work? If yes, congratulations! I am really impressed.
If not, what is the error that appeared in your terminal window? I would bet that you got "Warning: Duplicate variable definition". What does it mean? How to fix it?
There is only one variable in the short program we have provided. If you don't remember what it is, run a search on "variable" on this web page. When pressing next to go through all matching strings, you should at some point end up on this sentence "What we do here is declare a variable called circle and have it hold the definition of a new Sprite Object."
This is correct, we declared a variable called circle. An issue with object oriented languages is that variables need to be declared the very first time they are being used. This is the var part of the line. This means we define something called "circle" that from now on we will use as a variable. You have to declare a variable the very first time you use it. You cannot declare a variable more than once.
If you tried to copy and paste the code multiple times to create multiple shapes, chances are that you did this:
var circle:Sprite = new Sprite(); circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill(); addChild(circle); var circle:Sprite = new Sprite(); circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill(); addChild(circle);
That doesn't work because twice you get to create a brand new variable that as for name "circle". What you need to do is use a different name each time you create a new variable.
This will work:
var circle1:Sprite = new Sprite(); circle1.graphics.beginFill(0xFF794B); circle1.graphics.drawCircle(50, 50, 30); circle1.graphics.endFill(); addChild(circle1); var circle2:Sprite = new Sprite(); circle2.graphics.beginFill(0x0083D7); circle2.graphics.drawCircle(50, 50, 15); circle2.graphics.endFill(); addChild(circle2);
Something else will work. Can you guess? Do we necessarily need to define different drawing objects for circles, rectangles, etc. Can we not draw different shapes in the same sprite? Have a try.
var s:Sprite = new Sprite(); s.graphics.beginFill(0xFF794B); s.graphics.drawCircle(50, 50, 30); s.graphics.endFill(); s.graphics.beginFill(0x0083D7); s.graphics.drawCircle(50, 50, 15); s.graphics.endFill(); addChild(s);
Challenge
Can you draw a house, with roof, chimney, window, door?
If not, what are you missing? What about the roof? How to draw a triangular roof? How to find the information you need to draw a triangle? If you go to google.com and run a search on "actionscript 3" triangle, do you find any page that help find out how to draw a triangle?
Btw, how to draw a simple line? This could come in handy. After all, a triangle is a shape made of three lines.
If you had no success with Google, try the adobe live documentation. Can you draw a simple line or a triangle now?
Clarifications
But, but, if I was to use Flash CS3, I wouldn't have to bother about all that package and class definition stuff. Yes and No. If you were to type your code directly within your authoring environement, this is correct, you wouldn't have to bother with these extra lines. If you were to rely on an external .as file like we demonstrated here, you should have to do so.
Have a try, use the following program
import flash.display.Sprite; var circle:Sprite = new Sprite(); circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill(); addChild(circle);
And try to compile it with the method we described above. You will get the following error message: "file found in a source-path must have an externally visible definition. If a definition in the file is meant to be externally visible, please put the definition in a package."
Try adding the package definition:
package { import flash.display.Sprite; var circle:Sprite = new Sprite(); circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill(); addChild(circle); }
You will get this error: "A file found in a source-path can not have more than one externally visible definition. circle;rect".
In other words, you must use the package and class definition constructs whenever you code is in ".as" files. What we have given above as the correct file to run
package { import flash.display.Sprite; public class FilledCircle extends Sprite { function FilledCircle():void { var circle:Sprite = new Sprite(); circle.graphics.beginFill(0xFF794B); circle.graphics.drawCircle(50, 50, 30); circle.graphics.endFill(); addChild(circle); } } }
is really the minimal file you can write. No worries, that's simply a matter of getting used to add that package line and public class line at the top of any ".as" file.