AS3 101: Variables - Basix

Twice a month, we revisit some of our readers’ favorite posts from throughout the history of Activetuts+. This classic tutorial was first published in June, 2009 and was the first in what has become an astounding series.

This is the beginning of a series which will walk through some of the fundamental concepts of programming, as they apply to ActionScript 3.0. To kick things off, we'll talk about variables.

AS3 101

This tut is aimed squarely at those who have little-to-no scripting experience, but if you've used variables without really getting into the intricacies of datatyping and casting, you may want to follow along.

Introduction

Over the following steps, we'll build a simple example, the main feature of which is the row of buttons that act as a group. The currently selected button has a different appearance, it can't be clicked on again and the appearance is restored to its original state when another button is clicked. We'll use a variable to keep track of what's going on.

Step 1: What are Variables?

First things first: let's define what a variable is. If you remember high school mathematics, you may recall that variables are "stand-in" values. That is, they are symbols (usually single letters, such as "x", or the "E" and "m" in E=mc2) which represent a numeric value. It is understood that the value might change depending on other factors in an equation.

In programming, a variable is exactly the same thing, with two main exceptions. First, in programming, a variable can hold more than just a number. It can hold a sequence of text characters (called a "string"), it can denote true or false (called a "boolean"), or it can hold something much more complex, like a date, an XML document, or a movie clip.

The second main difference with mathematics is that programming variables usually have descriptive names, rather than just a single-letter name. There are exceptions, of course: "x," "y," and "z" are commonly used to reference positions and "i" is commonly used denote the current iteration through a loop. A name which is relevant to the value being stored is not only common, but also helpful in keeping your program legible. For instance, if you wanted to keep track of how many particles you have on screen, you might name your variable "particleCount" or "totalParticles."

Like mathematic variables, programmatic variables have the potential for being changed during the course of the program. For instance, if you started with 10 particles, the variable "particleCount" would have the numeric value of 10. However, if you generated 10 more particles, the variable would then have the numeric value of 20. This is one of the key features of variables. You have a name that references a value, but that value is not necessarily going to be the same every time you access it. This is a mysterious but powerful aspect of variables. You'll learn to appreciate this, even if it's confusing at first.

To sum up this definition, a variable is basically a container to which you assign a name and in which you put a value. You can always get the value contained inside by referencing the variable by name and you can put a new value inside the container at any point. Any time you access the variable by name, you get the current value contained therein. For further reading, you may want to see what Wikipedia has to say about variables.

Step 2: Declaring a Variable

Enough theory, let's actually get to work with making variables. Create a new Flash document (ActionScript 3.0). Click on the first frame of the first layer (it should be the only frame).

Open up the Actions panel by choosing Window > Actions (or pressing F9 on Windows or Opt-F9 on Mac).

In the Actions panel, type the following:

var message;

At this point, the varible is declared. This means that the container exists, but currently has no associated value.

This is the bare minimum you need to declare a variable. The word "var" is known as a keyword, meaning it's reserved by the ActionScript language and has a specific meaning. In this case, it declares a variable. It needs to be followed by the variable name you want to use; if you don't follow the var keyword with a variable name you'll get an error when you try to test the movie.

Step 3: Naming your Variables

There are a few rules you should follow when naming your variables. Some are enforced by the ActionScript compiler, others are just conventions which, when followed, help you and others make better sense of your code.

First, the ActionScript language dictates that you can only use certain characters in your variable name. These are any alpha-numeric characters (letters and numbers), the underscore and the dollar sign. Any other character (hyphens, the space, the period, etc) is not allowed. Usually this is because many other characters have special significance in ActionScript.

ActionScript also imposes the rule that the variable name must not start with a number. Numbers are, however, allowed after the first character.

It also bears mentioning that ActionScript is case-sensitive, meaning that you must match the letter's case when referring to a variable. In otherwords, the variable "message" is not the same as the variable "MESSAGE". This may seem restrictive as first, but there are actually good reasons for enforcing this. Space doesn't permit a discourse on these reasons, however. For now, just learn to type your variables' names exactly the same each time you want to use them.

The ActionScripting community at large has come to a general consensus on how to name your variables, although the following rules are more conventions and guidelines, rather than being enforced by ActionScript.

For starters, you should use descriptive names. This is a sort of self-documenting technique. If you name your variable "message," it's likely you already have an idea of what the intended role of the contained value is. If it were simply "m," then that's far less clear. It's tempting to use abbreviated variable names and while you are initially writing your script it might mean less typing and still make sense. The next person to look at your code, or you yourself six months later, will likely be confused.

Another convention is the use of camel case. This is a technique for turning two or more words into a single word. Remember that you can't use spaces (or any other white space, for that matter) in your names, so if you wanted to use the phrase "total particles" you have to find a way of getting rid of that space. "totalparticles" works, but the separation between the words is lost. Camel case is a method of capitalization that says that the entire word is lower case except for the first letter of each word, with the exception of the first letter of the first word. In other words, applying camel case to "total particles" results in "totalParticles".

Step 4: Setting a Value

Now that our variable is declared, we can put a value into it. On the next line of the Actions panel, type the following code:

message = "Hello";

We start by simply using the variable by its name. Then we follow it with an equals sign, which is known as the assignment operator. Following that, we have a quoted sequence of characters (ending with a semi-colon, which is just the way you end lines in ActionScript - you'll see a lot of terminating semicolons in code).

The assignment operator requires that there be something on either side of it. It works by taking the value on the right side ("Hello", in this case) and putting it into the variable on the left side (message).

If we were to run this code, we would have a variable named "message," which contains a value of "Hello." It's not doing anything else, so there's nothing to see at the moment, but it may be a good idea to test the movie anyway to make sure you don't get any errors, in case you typed something in wrong.

The script should look like this so far:

Step 5: Getting the Value

We now have a named container that has a value inside of it. Let's access that value. In this case, we'll simply trace the value to the Output panel.

On a new line of code, write the following:

trace(message);

The whole script will look like this:

As you may know, the trace function takes whatever you pass to it in between the parentheses and puts it into the Output panel. When you test the movie, you should see the Output panel open automatically and the value of the message variable ("Hello", without the quotes) printed to it.

Any time you use the variable by name and are not putting it on the left side of the assignment operator (the equals sign), you are asking ActionScript to get the value contained by the variable and use that value. This is called evaluating the variable.

Step 6: Manipulating the Value

Now let's prove that we can put different values into the same container. On the next line, let's set the value of the message variable again:

message = "How are you?";

And then on the line after that, trace it out again:

trace(message);

The whole script will look like this:

Run the movie and you should now have two traces:

Notice that lines 3 and 5 are identical – they both trace message, but they produce different results! Each time we ask for message to be traced, the current value of the variable is evaluated and used. First it gets set to "Hello" and that shows up in the Output panel. After that we set it to "How are you?" and then that shows up in the Output panel.

It's not rocket science, but this is one of the more confounding aspects of using variables. If you can master this, you'll be well on your way to becoming an ActionScript guru.

Step 7: Understanding Datatypes

ActionScript supports something called strong typing. It's an interesting language in that it's only strongly-typed if you tell it to be so and it can be strongly-typed at certain points and weakly-typed in others. There is something to be said for the ease of use of a weakly-typed language, but most serious programmers will be able to talk for a few hours on the merits of strong typing. So what is it?

Strong typing simply means that when we declare a variable, we can also declare what kind of value can be put into it. That is, if we say that our message variable can only contain a string (as it happens to do so currently), then if we tried to put a number or date into it, ActionScript will complain in the form of an error. Causing errors might seem like a hindrance, but when you empower the computer to catch your errors for you, you actually end up saving time. Weakly typing your variables will avoid compiler errors, but might allow logical errors (for instance, trying to uppercase a number), in which case things can fail without warning. Allowing room for compiler errors through strongly-typing your code actually saves you time in the long run.

A datatype is, in a nutshell, the type of data that a value is. That is, values can be a string, a number, a boolean, a date, an XML document, a movie clip and many more built-in types - even types you create. Our message variable is implicitly of type String (note the capital "S"), so let's make that type explicit. We'll make our code strongly-typed, by decalring a datatype. Back on the first line of code, where we declare the message variable, modify it to read:

var message:String;

The colon specifies that what's about to follow is a datatype and then you'll see the datatype itself. All built-in datatypes will start with a capital letter and that is a common convention for custom datatypes as well. We won't be getting into writing custom datatypes, however.

If you run the code at this point, you should see that it functions exactly the same.

Step 8: Causing an Error

We can, however, illustrate how strong typing works by intentionally causing an error. Let's add some more code, assigning the variable to yet another value. This time, though, we'll try to put a number into it instead of a String. At the end, type the following:

message = 42;
trace(message);

Test the movie and you should see the following error:

1067: Implicit coercion of a value of type int to an unrelated type String.

The language is a little archaic, but it simply means that we have a number (or an "int") value and we tried to put it into a variable that was previously declared to only contain Strings.

Let's throw another error. Delete the two lines of code you just added and replace them with the following line:

isNaN(message);

Then run the movie. You should get the following error:

The isNaN() function expects a number to be passed in to it through the parentheses (NaN means Not a Number, which is a special value meaning a number that doesn't actually have a value. This function tests for that case). Since we're passing in a String, we get basically the reverse error of what we had before.

Note that if you remove the String datatype from the variable and then re-run these two experiments, you won't get an error. The code will actually execute and in this case the lack of datatyping isn't such a big deal. In larger projects, having this kind of insurance can prevent errors and bugs that bring down your whole movie.

Step 9: Create a Button

That should be enough of an introduction; let's see a specific use of variables in action. We'll now start making the button group example shown at the start of this tutorial.

Create a new ActionScript 3 Flash file and create some art to serve as a button. Turn it into a movie clip.

Step 10: Create Four Instances

Drag the symbol on the stage four times so that there are four instances of the button. While it's not necessary for the function of the movie, you may want to arrange them in a row at the top of the stage. Give each an instance name by clicking on each one individually and typing the name into the instance name field of the Properties panel.

I've named my buttons "button1," "button2,""button3," and "button4." For simplicity in following along with the code, be consistent and use my names.

Step 11: Create a Text Field

Underneath the row of buttons, create a dynamic text field, give it an instance name (I used "output") and go ahead and make it as big as will fit on the stage. The purpose of this text field will be to log the names of the buttons as they are clicked. We don't need too much horizontal space but should have as much vertical space as possible.

Step 12: Hook Up Click Listeners

Create a new layer to hold your code, lock it and then click in the frame for that layer. Open the Actions panel. Write the following code to hook up an action to respond to mouse clicks for each button:

For now, the actual action taken in response to a click is trivial, but it's enough for us to test. If you've done everything correctly so far, you should be able to test the movie and click on each of the four buttons. Every time you click, you will see the word "click" show up in the Output panel.

Step 13: Understanding Event.target

You may be wondering how we'll accomplish our goal with just a single function. How will that one function react appropriately for each of the four different buttons?

Without getting into too much detail into the event paradigm of ActionScript 3, every function that acts as an event listener will receive an event object as a parameter. There are several kinds of event objects, from regular Event objects to MouseEvents to KeyboardEvents to ProgressEvents and more, but every event object will have a few common characteristics. One of the most useful of these is the "target" property. Every event object defines a target property that points to the thing that actually caused the event.

We can tell which button was clicked by accessing the target of the MouseEvent in the function. To see this in action, change the function contents to:

trace(event.target.name);

The whole script looks like this:

Rerun the movie and click on the buttons again. You should see the appropriate name show up in the Output panel.

This works because the event object itself is held in the variable called "event." That object has a property (a property is basically a variable, except that it belongs to an object) called "target", and using dot syntax we can access the target variable from the event variable. The target is the movie clip that was actually clicked and caused the event. By accessing the name property of that movie clip, we can get an indication of which button was clicked to print to the Output panel.

Step 14: Output the Button Name

Let's now actually do something when a button is clicked. We'll put the button's name into the text field. Add the following to the buttonClick function (replacing, if you like, the trace statement)

The first line puts the name of the clicked button into the text field. The appendText() method will take the current text and add to it. We'll put a newline character (the "\n") at the end of the added text to make sure the next bit of text added will be on a new line.

The second line makes sure that the last line of text is always visible. In a nutshell, this line sets the scroll amount (which line of text is at the top of the visible area) to the maximum amount based on how many lines there are.

Step 15: Create a Selected State

Remember that our goal is to make the clicked button the selected button, so we want to visually represent that. To easily make a visual change to the button, we'll just set the alpha to something slightly transparent.

Replace the trace statement with the following:

event.target.alpha = 0.7;

The alpha property of a movie clip adjusts the transparency and ranges from 0 to 1, with 1 being fully opaque. Therefore, 0.7 is something that's 70% opaque, or 30% transparent.

Run the movie and click on a button. You should see it change. Of course, we still have quite a bit to implement, so once a button obtains the selected look, it stays that way.

Step 16: Disable Event.target

You'll notice that if you click on a button, you can continue to click on it, as evidenced by the name showing up each time you click. We want something like a group of tab buttons, where a button that is currently selected can't be clicked. We can easily accomplish this by setting the mouseEnabled property of the recently-clicked button (still event.target) to false.

event.target.mouseEnabled = false;

The whole script at this point should look like the following:

Step 17: Variable to Hold the Current Button

So far we're off to a good start, but while the button is reacting appropriately when we click it the first time, we have issues after that. The button is kind of stuck in the selected state and is never restored to its normal state when another button is clicked.

Now we can introduce the variable that will solve all of our problems. We need a variable that will contain the movie clip that is the currently selected button. By storing it in a variable, the information about which button is currently selected can persist from click to click.

We'll call it "currentButton" and we'll give it a datatype of MovieClip. At the top of the script, write this line:

var currentButton:MovieClip;

Step 18: Set the Variable to Event.target

Now, every time we click on a button, we want to track that button in the currentButton variable, so that at any given time we know which button is the current one. This is done with the following modification to the buttonClick function:

currentButton = event.target as MovieClip;

Notice the "as MovieClip" in the preceding code. We'll gloss over all of the gory details here, but this is a necessity due to strong typing. Our currentButton variable is declared as being a MovieClip. However, the target property of the Event object is declared as being an Object, which is a very generic datatype. The target is defined as an Object so that it can be generic; lots of things can create events and so the target won't necessarily always be a MovieClip. The problem is that the two datatypes don't really match; we're promising that only MovieClips will go into the currentButton variable, but we're trying to put an Object in.

The best thing we can do is assume that the event's target is, in fact, a MovieClip and so we perform a cast on it. The "as" operator takes the value on the left and treats it as though it were of the datatype specified on the right. The assumption is reasonable, since the code is inside of a function that should only ever get called when the user clicks on a MovieClip and that MovieClip creates the MouseEvent.

Note that casting is not without its problems. The biggest problem comes in the form of a cast that can't be honored. For example, if we were to try to cast our event.target as an XML object, well, then that wouldn't work at all, would it? MovieClips and XML objects have very little in common. When the cast is attempted, we would get an empty value back, which leaves us with a broken program. If we're lucky we'll get a runtime error saying that the cast can't be completed; if we're unlucky we'll get the empty value and are left wondering why things didn't work as planned.

Casting should be avoided if its not necessary, but in some cases (like this one) it's pretty much the only option. If we didn't cast the target, we'd get a compiler error. Go ahead and try it if you'd like to see what happens.

Step 19: Use currentButton

While not strictly necessary, we may as well use our new currentButton variable instead of event.target in the body of the function. It's not necessary because while we're in the function, we have access to event.target and our code will work just fine without making the following change. However, there are two compelling reasons to get in the habit of using typed (and casted, if need be) variables where possible.

The first reason is the main reason. As mentioned in the last step about casting, event.target is not typed as a MovieClip. Yet we know that it is, so we cast it as such. Think back to step 9, where we deliberately typed a variable as one thing and tried to use it as another, which caused errors. Now, if we go and tell the variable currentButton to set its alpha to 0.7, currentButton is a MovieClip and MovieClip has an alpha property and all is good. If we accidentally tried to set the aplah property (it happens more often than you would think), Flash would complain about it and let us know and we'd be able to correct our mistake quickly. Using event.target (which is a very generic, loosely-typed variable), it may take longer to find that typo.

The second reason has to do with performance. In this particular case, we're not going to see huge gains from using a typed variable instead of event.target. In ActionScript 3, it is faster to use a value out of a single typed variable that it is out of an untyped property (as event.target is). In critical applications this might give you an extra few processor cycles.

So, in this step we are simply changing out occurences of event.target with currentButton, after it has been set.

Your code should look something like the following:

Step 20: Deselect the Old Current Button

Now that we have a variable declared and holding a value, we can use it to restore the visual appearance of the previously selected button. That is, if you click on button1 and it changes appearance, then you click on button2, we want button1 to look normal again.

The next bit of code needs to happen before we set the currentButton variable. Otherwise, we'll be affecting the current button, not the previous button.

currentButton.alpha = 1;

This will restore the previous button's appearance, but we won't be able to click on it. We previously disabled it by setting its mouseEnabled property to false, so we can enable it by setting it back to true. Place this code immediately after the last bit of code we wrote:

currentButton.mouseEnabled = true;

The code should look like this:

Step 21: Check for null Value

If you tried running the movie after the last step, you'll have run into a runtime error involving a "null object." This is ActionScript's way of saying that a variable didn't have a value before you tried doing something with it.

What happened was that when the movie starts, the currentButton variable is declared, but it doesn't have a value yet. It only gets a value when you click on a button. Well, when you click on a button, the buttonClick function runs and the first thing it does is try to set the alpha of whatever is in currentButton. Unfortunately, nothing is in currentButton and so the "null object" error gets thrown. At that point, script execution stops and so we end up never getting to a place where we can actually set currentButton.

This is easily avoided, though. We simply need to check that currentButton doesn't equal null before continuing. Replace the first two lines with:

Without getting into too much detail, this sets up a condition that only runs the statement after the parentheses if the statement inside the parentheses has a value. In other words, if currentButton has not been set, then skip the part about setting its alpha and pick up with the next line of code.

At this point, you have created a variable. It has a name and a datatype. It stores several different values over time, so that at certain points in time you can track the current value and do something with it. You learned about casting and why variables are the building block of all programs of any complexity.

I hope you enjoyed this beginner's article, feel free to leave questions and opinions in the comments section. We have plenty more tutorials planned for the AS3 101 series, so stay tuned!

Dru Kepple works at Summit Projects as an ActionScripter, and teaches Flash at the Art Institute of Portland. He writes about Flash-ish things at the Summit Projects Flash Blog. He's always thinking about ActionScript. He's thinking about it right now, in fact.