interactive scripting - CGR C/092 - fall 2004
Philip van Allen - v a n a l l e n @ a r t c e n t e r . e d u

room 142, Monday 4:00pm-7:00pm
all materials on this web site © copyright 2004, Philip van Allen
 
week 04a - variables & variable scope, properties, Math.random(),

 
reading : 

variables : 


  
conditionals - chapter 7, loops - chapter 8

more details on how variables work

variable assignment : 

values persist until changed

Once a variable is created and a value is assigned to the variable, that value persists in the variable until a new value is assigned, or until the Flash program exits. But as soon as a new value is assigned to a variable, the old value is lost forever. So if a value is assigned to a variable in frame one of a movie, the value will still be there if we check it in frame 20 of the same timeline. E.g.

In frame 1:

var friend = "George";

In frame 20:

trace(friend);

When the code in frame 20 is executed, the string "George" will show in the output window. But if we make several changes to the value of the variable, only the last value will persist. E.g.

In frame 1:

var friend = "George";
friend = "Molly";
friend = "Sydney";

In frame 20:

trace(friend);

In this case, the result shown on frame 20 will be "Sydney".

 

 
accessing variables : 

local variable scope

So far, our variables seem to be accessible from anywhere by simply referring to their name, but this is not always true. In fact, variables are always associated with a particular timeline. This is referred to as the scope of the variable--in other words, the local scope of a variable is the timeline where it's created or accessed. Within that timeline, the variable can be addressed by its simple name. In the above example the variable "friend" was declared and assigned a value in one frame, and the value was retrieved in another frame--this works because the local scope of the variable includes both statements where the variable is accessed. Within a timeline, the local scope of a variable includes:

  • different frames of the same timeline
  • any buttons in the timeline
  • any functions associated with that timeline

The local scope of a variable used in a timeline does not include any movieClips on the current timeline. For example, if a variable were defined in a button on the movie timeline, that variable cannot be accessed directly from a movieClip that's been placed on the stage in the same timeline as the button.

In general, if variables are used in different timelines (timelines are either in the main Flash movie or in a movieClip), variables cannot be accessed by their simple names. For another example, if a variable is declared and assigned a value in movieClip A, it cannot be addressed directly in movieClip B, even though both movieClips are on the same timeline. This is because each movieClip has its own timeline, and that is the local scope of the any variables used within that timeline. To test this, do the following:

  1. create two movieClips on the main timeline, and name them a_mc and b_mc
  2. in movieClip a_mc, put the following code:
               
    on (release) {
        var theName = "George";
        trace(theName);
    } 
              
  3. in movieClip b_mc, put the following code:
               
    on (release) {
        trace(theName);
    } 
                

As you'll see, clicking on a_mc shows the value of the variable "theName" to be "George". But if you click on b_mc, the value is shown to be "undefined". This is because the variable "theName" in a_mc has a scope limited to the timeline in that movieClip, which does not extend to the b_mc movieClip. It is actually common for different movieClips to use the same variable names, where each movieClip has its own value. To test this, change the code in b_mc to:

on (release) {
    var theName = "Molly";
    trace(theName);
} 

Note that these rules of local scope in a timeline also apply to movieClip functions, properties, and methods. I.e., making a change to the "_rotation" property of one movieClip will not affect the rotation of another instance of the same clip. And if a function is defined in one timeline, it will not be accessible to other timelines using the simple function name. Which leads us to:

 

 
accessing variables etc. : 

in different timelines

As we've seen, we can only access variables and other timeline characteristics in the current timeline when using the simple names. But what if we wanted to access variables (or functions or methods) in other timelines?

movieClip accessing the main timeline

For example, suppose we defined a counter variable named scoreCounter in the main timeline of the Flash movie, and needed to increment this counter from code in a movieClip. The code in the movieClip event handler cannot simply refer the name scoreCounter. Instead, it must explicitly refer to the name of the timeline that contains the counter. In this case, it would use the special keyword "_root" to refer to main timeline. In the main timeline frame one, the code might look like this

var scoreCounter = 0;

and in the movieClip, the code would look like this, referring to the variable with an absolute reference to the timeline that contains the variable::

on (release) {
    _root.scoreCounter++;
    trace(_root.scoreCounter);
} 

Another way to access this variable uses a relative reference to the variable from the current movieClip with the special keyword "_parent". The _parent keyword refers to the timeline that contains the current timeline (in this case the main timeline):

on (release) {
    _parent.scoreCounter++;
} 

Absolute and relative references are equally valid to use. Absolute references show you exactly where the variable (or other timeline characteristic) is in the movie. Code using absolute references can be moved anywhere, and the same variable will be affected regardless. Relative references describe the location of the variable in relation to the current timeline, which is sometimes more clear. Also, if the code has to be moved to a timeline within a timeline, it may be more portable, since it still refers to just the timeline above or below rather than the main timeline—i.e. the relationship of the timelines is preserved.

The same rules of referencing apply to functions and methods. For example, if a movie clip needs to change the position of the main timeline (rather than the movieClip's timeline), the code would be written like this:

on (release) {
    _root.gotoAndPlay("start");
} 

In the case of functions, we can defined a function in frame 1 of the main timeline:

function myFunction() {
    trace("hi");
}

In the movieClip where we want to access the function the code would be:

on (release) {
    _root.myFunction();
} 

main timeline accessing a movieClip

In the situation where code in the main timeline needs to access characteristics of a movieClip placed in the root timeline, the name of the movieClip instance is used. For example, suppose there is a button and a movieClip on the stage of the main timeline. We want to change the rotation of the movieClip each time someone clicks on the button. First, keep in mind that buttons have the same scope as the timeline in which they reside, and do not have a separate scope like movieClips do. This may be hard to get used to, since buttons seem similar to movieClips—but they aren't because the don't have a timeline. Let's name our movieClip instance square_mc. To change the rotation of the square movieClip, the following button code uses a relative reference:

on (release) {
    square_mc._rotation += 10;
} 

The above code is relative because square_mc is a child of the main timeline. If we used an absolute reference, the code would start with _root, the name of the instance, and then the property name. Note that properties work just like variables defined within a movieClip:

on (release) {
    _root.square_mc._rotation += 10;
}

movieClips inside of movieClips

For a more complicated example, suppose that an instance of the square called square_mc was placed inside a movieClip called boxMan_mc that's on the main timeline. The movieClip heirarchy would look like this:

main timeline --> boxMan_mc --> square_mc

If we wanted to write code using an absolute reference to change the rotation of square_mc, it would look like this:

on (release) {
    _root.boxMan_mc.square_mc._rotation += 10;
} 

 

 
avoid reference problems : 

use the keyword "this"

There are many situations where it is complicated or impractical to know the relative or absolute path to an object we want to affect. In these situations, you can use a powerful keyword called "this" to refer to the current object timeline. The "this" keyword works no matter where the object is, even if it is buried several levels deep of movieClips inside of movieClips.

For example, suppose we wanted a function that rotated and moved to the right any movieClip that used the function. Obviously, we wouldn't put every name of every movieClip in the function. Instead, we would write the function to accept the reference to the movieClip as an argument, and the rotate and move whatever movieClip that argument refers to. In the main timeline, we would define the function like this:

function rotateMove(aClip) {
    // aClip is used as a temporary way 
    // to refer to the clip to be changed
    aClip._rotation += 10;
    aClip._x += 10;
} 

In the movieClip, we would use code like this:

on (release) {
    // we use this to send the reference
    // of the current movieClip to the 
    // function, which then operates on it
    _root.rotateMove(this);
} 

Another situation that works well with the "this" keyword is the case of using methods on the current movieClip. For example, a common thing to do is move the current movieClip's timeline to a different frame. If we used the normal reference approach, we might have to write the following code for the earlier example of a movieClip inside of a movieClip:

on (release) {
    _root.boxMan_mc.square_mc.gotoAndPlay("win");
} 

Instead, we can use the "this" keyword to write much simpler code. Plus, because the code doesn't refer to any particluar movieClip, we can copy this code to any movieClip, and it will still work:

on (release) {
    this.gotoAndPlay("win");
} 

 

 
     

all materials on this web site © copyright 2004, Philip van Allen

top