Macromedia Flash MX ActionScripting: Advanced Training from the Source

As you've seen up to this point, loops provide a great way of automating a set of scripting tasks. However, loops can accomplish more than a straight, linear, repetitive execution of a set of actions. A nested loop, or a loop placed inside another loop, can be useful for creating a looping sequence that executes a set of actions, changes a bit, executes those same actions again, changes a bit, and so on.The following is an example of a nested loop:

var i = 0; while (++i <= 10) { var j = 0; while (++j <= 10) { // perform these actions } }

The actions in the above loops will be executed 100 times. Here's the underlying logic: The outer loop (which uses i ) is set to loop 10 times. With each iteration of this outer loop, two things occur: The variable j is reset to 0, which then enables the inner loop (which uses j ) to loop 10 times itself. In other words, on the first iteration of the outer loop, the inner loop will loop 10 times; on the second iteration, the inner loop will again loop 10 times; and so on.

Nested loops are great for breaking up repetitive tasks into a hierarchical process. To help conceptualize this, think about writing a letter. A letter represents a nested-looping process in which you start on Line 1 and write 100 characters, then drop to Line to 2 and write 100 characters, and so on. If you were to write a 25-line letter, an imaginary script to do the work might look like the following:

var i = 0; while (++i <= 25) { var j = 0; while (++j <= 100) { // type a character } // drop down to the next line }

Keep in mind, too, that you aren't restricted to nesting just one loop inside of another: You can use as many loops within loops as your project requires.

In this exercise, you'll use nested loops to create a grid of images that appear when an item in the drop-down list is selected.

  1. Open pictureShow2.fla in the Lesson 10/Assets folder.

    On the top of the stage, you'll see three movie clip instances: pictures1, pictures2, and pictures3. In this exercise, you'll duplicate one of these three movie clips (depending on which item in the drop-down list is selected) to form a grid of images on the screen.

  2. With the Actions panel open, select the dropDownList movie clip instance and add the following function to the load event:

    function itemClicked (pictureID) { picToDuplicate = "pictures" + pictureID; xSpacing = 160; ySpacing = 120; xStart = 190; yStart = 30; }

    In a moment, we'll set up the list buttons that were duplicated in the previous exercise to call this function and pass it a parameter value pictureID when clicked. When finished, this function will copy one of the three picture movie clip instances at the top of the stage four times to form a two-by-two grid and to send each duplicated instance to a unique frame to display an image.

    The first line in this function creates a variable called picToDuplicate . This variable's value which is based on the pictureID value (of 1, 2, or 3) passed to the function when it was called will be set to picture1, picture2, or picture3, which happen to be the names of the instances on stage containing pictures. We'll use this value in a moment to identify which of these instances to duplicate.

    The xSpacing variable represents the amount of space you want to allot between the left sides of the two movie clip instances found on the same horizontal row. The ySpacing variable indicates how much space you want between two movie clips in the same column. The values of these spacing variables are fairly arbitrary and will depend largely on how much space you like to see between movie clips.

    The next two variables, xStart and yStart , represent the starting position of the first duplicated movie clip in relation to the stage. Any subsequent movie clip duplicates will be positioned relative to this point.

  3. Add the following script to the bottom of the itemClicked() function (that is, add it to the function definition):

    v = 0; i = -1; while (++i < 2) { j = -1; while (++j < 2) { ++v; name = "picture" + v; _root[picToDuplicate].duplicateMovieClip(name, v); _root[name]._x = xStart + i * xSpacing; _root[name]._y = yStart + j * ySpacing; _root[name].gotoAndStop(v); } }

    Here you see a loop with a nested loop the portion of the function that actually creates the two-by-two grid of movie clip instances. A single loop would create just a single column of movie clip instances. A nested loop, in contrast, creates two instances in a column, alters the script slightly to "move" the column coordinates, then creates another two instances in a column (which we'll explain in a moment). The following describes the logic that allows it to work.

    The outer loop (beginning at Line 3) in the above script increments i by one (++i ), thus setting a value of 0. The condition of this outer loop says that as long as i is less than 2, execute the actions below. Thus, because 0 is less than 2, the actions within the loop are executed. The first action sets the value of j to -1. Immediately following that, a nested (inner) loop appears, which uses the value of j . First, j is incremented by one (++j ) and the condition is set that says as long as j is less than 2, continue to loop through the actions that follow. The script will continue to do nothing else but execute the actions in this inner loop until that condition becomes false . During the first iteration of this inner loop the value of v is incremented by one (++v ), giving it a value of 1. This variable's value is used several times in the lines of script that follow. Using by-now-familiar ActionScript, the appropriate picture movie clip instance is duplicated and positioned. During the second iteration of this inner loop, the value of j is incremented by one (as shown in the loop's conditional statement), giving it a value of 1, which is still less than 2 thus, the actions within that loop are executed once again. This inner loop cannot perform a third iteration because j would be incremented again (++j ), making it equal to 2 (a condition that exits the inner loop). As a result, the script revisits the outer loop. At that point, i (used by the outer loop) is incremented by one (++i ), giving it a value of 1, which is still less than 2, so the actions in the outer loop are executed again. As a result, the value of j is reset to -1, and the actions in the inner loop are executed two more times (as previously described). This can be a tricky concept to grasp, so review the logic until you understand it.

    To achieve the effect of creating a two-by-two grid of movie clips (the proper spacing), take a look at the following lines of script:

    _root[name]._x = xStart + i * xSpacing; _root[name]._y = yStart + j * ySpacing;

    The first line uses the current value of i to set the horizontal spacing; the second line uses the current value of j to set the vertical spacing when a movie clip is duplicated. You've already learned that with each outer loop iteration, the inner loop performs two iterations. Thus, while i has a value of 0, the value of j is both 0 and 1, then i is incremented to a value of 1, and once again, the value of j is set to both 0 and 1. Knowing the values of xStart , xSpacing , yStart , and ySpacing , as well as how the values of i and j are incremented in the looping process, we can determine the spacing for each clip as follows:

    First instance duplicated

    _x = 190 + 0 * 160;// x set to 190 _y = 30 + 0 * 120;// y set to 30

    NOTE

    Remember that in an expression, multiplication always occurs before addition (as shown).

    Second instance duplicated

    _x = 190 + 0 * 160;// x set to 190 _y = 30 + 1 * 120;// y set to 150

    Third instance duplicated

    _x = 190 + 1 * 160;// x set to 350 _y = 30 + 0 * 120;// y set to 30

    Fourth instance duplicated

    _x = 190 + 1 * 160;// x set to 350 _y = 30 + 1 * 120;// y set to 150

  4. Add this final action as the last line in the itemClicked() function definition:

    removeButtons();

    This action calls a function you're about to create named removeButtons() , which will remove the drop-down-list buttons after one has been clicked and the picture grid created.

  5. Create the removeButtons() function at the end of the load event of the currently selected movie clip instance:

    function removeButtons() { var i = -1; while (++i < numberOfButtons) { name = "item" + i; this[name].removeMovieClip(); } }

    This function uses a simple while loop to loop through and remove all of the buttons (which are actually the duplicate movie clip instances item0, item1, and item2) that make up the drop down-list choices under the Menu button. This loop works in similar fashion to the loop we used to create the duplicates that make up the list. Let's analyze this loop's syntax.

    You'll remember that the variable numberOfButtons (used in the third line of the script) was originally created and assigned a value in the populateList() function discussed in the previous exercise. Its value is based on the length property of the info array. Because that array has three elements, the above loop will perform three iterations. On each loop the variable name is set based on the current value of i . The removeMovieClip() method is then used to remove the duplicate movie clip instances referenced by the current value of name removing the list of choices beneath the Menu button.

  6. Double-click the dropDownList movie clip instance to edit it in place. Double-click the item movie clip instance to edit it in place. Select the white button, open the Actions panel, and add the following script:

    on (release) { _parent.itemClicked(pictureID); }

    When you click the Menu button, a drop-down list is created by duplicating the item movie clip instance. Because the above script is attached to a button inside the item movie clip instance, the buttons in the duplicates will include this same script. However, during the duplication process (accomplished via the populateList() function we created in the previous exercise), a variable called pictureID is created inside each duplicate instance and in each instance, the variable has a different value. That value is 1, 2, or 3, depending on the value of i when the duplicate is created (review the structure of the populateList() function if this is unclear). When this button is clicked in any of the duplicated movie clip instances, the above script passes the value of the pictureID variable in that instance to the itemClicked() function that was defined on the dropDownList movie clip instance. The result is that a grid of images is formed on the stage. To make better sense of this, review the image in Step 2 of this exercise.

  7. Choose Control > Test Movie to test your work.

    Click the Menu button to display the list of choices. As you click any of the list buttons, you'll see that the grid of images is being created based on the value of pictureID that is being passed to the itemClicked() function. You'll also notice that the list choices are removed via the removeButtons() function.

  8. Close the test movie and save your work as pictureShow3.fla.

    In this exercise, you used nested loops to create a grid of images on the screen. While we could have manually dragged and placed four movie clip instances on the stage to accomplish the same thing, by using a nested loop, we've automated the entire process in such a way that with a couple of minor adjustments, our script can create anything from a two-by-two grid to a 100-by-100 grid. Using loops, and especially nested loops, in this fashion not only helps automate processes you might perform manually in the authoring environment, it also enables your projects to scale up or down dynamically based on conditions that exist while it plays.

Категории