Now that you've learned the fundamentals of movie clip programming, let's put this knowledge to use by creating a sample analog clock application, which exemplifies the typical role of movie clips as basic content containers. See also the various versions of the multiple-choice quiz posted at the online Code Depot.
In this chapter we saw how to create movie clips with attachMovie( ) and how to set movie clip properties with the dot operator. With these relatively simple tools and a little help from the Date and Color classes, we have everything we need to make a clock with functional hour, minute, and second hands.
First, we'll make the face and hands of the clock using the following steps (notice that we don't place the parts of our clock on the main Stage�our clock will be generated entirely through ActionScript):
Create a new, empty Flash movie.
Create a movie clip symbol, named clockFace, that contains a 100-pixel-wide black circle shape, centered on the clip's registration point.
Create a movie clip symbol, named hand, that contains a 50-pixel-long, vertical red line.
Select the line in hand; then choose Window Info (Flash MX) or Window Panels Info (Flash 5).
Because we want the hands to rotate around the center of the clock, we must position the line so that one end is at the registration point (the center) of the hand clip. Therefore, position the bottom of the line at the center of the clip by setting the line's x-coordinate to 0 and its y-coordinate to -50.
Now we have to export our clockFace and hand symbols, so that instances of them can be attached dynamically to our movie:
In the Library, select the clockFace clip; then select Linkage from the pop-up Options menu. The Linkage Properties dialog box appears.
Select the Export For ActionScript checkbox.
In the Identifier box, type clockFace, and then click OK.
Repeat Steps 1 through 3 to export the hand clip, giving it the identifier hand.
The face and hands of our clock are complete and ready to be attached to our movie. Now let's write the script that places the clock assets on stage and refreshes them with each passing second:
Add the script shown in Example 13-7 to frame 1 of Layer 1 of the main timeline.
Rename Layer 1 to scripts.
Skim Example 13-7 in its entirety first; then we'll dissect it.
// Create clock face and hands attachMovie("clockFace", "clockFace_mc", 0); attachMovie("hand", "secondHand_mc", 3); attachMovie("hand", "minuteHand_mc", 2); attachMovie("hand", "hourHand_mc", 1); // Position and size the clock face clockFace_mc._x = 275; clockFace_mc._y = 200; clockFace_mc._height = 150; clockFace_mc._width = 150; // Position, size, and color the clock hands secondHand_mc._x = clockFace_mc._x; secondHand_mc._y = clockFace_mc._y; secondHand_mc._height = clockFace_mc._height / 2.2; secondHandColor = new Color(secondHand_mc); secondHandColor.setRGB(0xFFFFFF); minuteHand_mc._x = clockFace_mc._x; minuteHand_mc._y = clockFace_mc._y; minuteHand_mc._height = clockFace_mc._height / 2.5; hourHand_mc._x = clockFace_mc._x; hourHand_mc._y = clockFace_mc._y; hourHand_mc._height = clockFace_mc._height / 3.5; // Update the rotation of hands with each passing frame function updateClock () { var now = new Date( ); var dayPercent = (now.getHours( ) > 12 ? now.getHours( ) - 12 : now.getHours( )) / 12; var hourPercent = now.getMinutes( )/60; var minutePercent = now.getSeconds( )/60; hourHand_mc._rotation = 360 * dayPercent + hourPercent * (360 / 12); minuteHand_mc._rotation = 360 * hourPercent; secondHand_mc._rotation = 360 * minutePercent; } // Update the clock every 100 milliseconds setInterval(updateClock, 100);
That's a lot of code, so let's review it.
We first attach the clockFace clip and assign it a depth of 0 (we want it to appear behind our clock's hands):
attachMovie("clockFace", "clockFace_mc", 0);
Next, we attach three instances of the hand symbol, assigning them the names secondHand_mc, minuteHand_mc, and hourHand_mc. Each hand resides on its own layer in the programmatically generated content stack above the main timeline. The secondHand_mc clip (depth 3) sits on top of the minuteHand_mc clip (depth 2), which sits on top of the hourHand_mc clip (depth 1):
attachMovie("hand", "secondHand_mc", 3); attachMovie("hand", "minuteHand_mc", 2); attachMovie("hand", "hourHand_mc", 1);
We want our clock centered � not in the top-left corner of the Stage � so, we center the clockFace_mc clip on stage and make it larger using the _height and _width properties. In this example, we assume the movie size is the default (550 x 400 pixels), but we could have used Stage.width and Stage.height to dynamically retrieve the dimensions of the movie at runtime. As an exercise, use Stage.onResize( ) to keep the clock centered even when the movie is resized.
clockFace_mc._x = 275; clockFace_mc._y = 200; clockFace_mc._height = 150; clockFace_mc._width = 150;
Next, we move the secondHand_mc clip onto the clock and make it almost as long as the radius of the clockFace_mc clip:
secondHand_mc._x = clockFace_mc._x; secondHand_mc._y = clockFace_mc._y; secondHand_mc._height = clockFace_mc._height / 2.2;
Remember that the line in the hand symbol is red, so all our hand instances thus far are also red. To make our secondHand_mc clip stand out, we color it white using the Color class. Note the use of the hexadecimal color value 0xFFFFFF (see the Color Class in the Language Reference for more information on manipulating color):
// Create a new Color object to control secondHand_mc secondHandColor = new Color(secondHand_mc); // Assign secondHand_mc the color white secondHandColor.setRGB(0xFFFFFF);
Next, we set the position and size of the minuteHand_mc and hourHand_mc clips, just as we did for the secondHand_mc clip:
// Place minuteHand_mc on top of clockFace_mc minuteHand_mc._x = clockFace_mc._x; minuteHand_mc._y = clockFace_mc._y; // Make minuteHand_mc shorter than secondHand_mc minuteHand_mc._height = clockFace_mc._height / 2.5; // Place hourHand_mc on top of clockFace_mc hourHand_mc._x = clockFace_mc._x; hourHand_mc._y = clockFace_mc._y; // Make hourHand_mc the shortest of all hourHand_mc._height = clockFace_mc._height / 3.5;
Now we have to set the rotation of the hands on the clock to reflect the current time. However, we don't just want to set the rotation once. We want to set it repeatedly, so that our clock hands animate over time. Therefore, we put our rotation code in a function called updateClock( ), which we'll call periodically:
function updateClock () { // Store the current time in now var now = new Date( ); // getHours( ) works on a 24-hour clock. If the current hour is greater // than 12, we subtract 12 to convert to a regular 12-hour clock. var dayPercent = (now.getHours( ) > 12 ? now.getHours( ) - 12 : now.getHours( )) / 12; // Determine how many minutes of the current hour have passed, as a percentage var hourPercent = now.getMinutes( )/60; // Determine how many seconds of the current minute have passed, as a percentage var minutePercent = now.getSeconds( )/60; // Rotate the hands by the appropriate amount around the clock hourHand_mc._rotation = 360 * dayPercent + hourPercent * (360 / 12); minuteHand_mc._rotation = 360 * hourPercent; secondHand_mc._rotation = 360 * minutePercent; }
The first task of updateClock( ) is to retrieve and store the current time. This is done by creating an instance of the Date class and placing it in the local variable now. Next we determine, as a percentage, how far around the clock each hand should be placed�much like determining where to slice a pie. The current hour always represents some portion of 12, while the current minute and second always represent some portion of 60. We assign the _rotation of each hand based on those percentages. We calculate the hourHand_mc clip's position to reflect not only the percent of the day but also the percent of the current hour.
Our clock is essentially finished. All that's left to do is call the updateClock( ) function with the following line of code, which refreshes the clock display every 100 milliseconds:
setInterval(updateClock, 100);
Test the movie to see if your clock works. If it doesn't, compare it to the sample clock .fla file provided at the online Code Depot, or check your code against Example 13-7. Updating the clock 10 times per second should create a nice smooth sweep of the second hand, but it may also be overkill (or a drain on performance of a larger piece).
Reader Exercise: Modify Example 13-7 to update the clock only once per second, and add a "tick-tock" sound synchronized with the second hand's movement (which should give the illusion of a nice firm snap).
Think of other ways to expand on the clock application: Can you draw the clock programmatically with the Drawing API? Can you make the clock more portable by turning it into a component? How about dynamically adding minute and hour markings on the clockFace_mc clip? Can you modify it to display different or multiple time zones? Can you create a stopwatch, complete with a reset button?