Tuesday 29 May 2007

Analog Clock Tutorial (FL1.1)


Many of you have asked for me to create a tutorial on how to create your own animated analog clock. In this tutorial, we will go through this process using a couple simple FSCommands.

First off, you will need to create 3 graphic symbols. Each symbol will represent the different hand on the clock. Thus, there will be a minuteHand, secondHand and hourHand graphic symbol (they don't have to be named this way).

Update: Registration does not have to be at the pivot point. Read below for more info.

Next you will need to create 3 movieclips. Each movieclip will house the corresponding graphic symbol undergoing a 360 rotation motion tween. Thus we can name them minuteAnimation, secondAnimation and hourAnimation.




UPDATE: The registration point does not need to be at the pivot point. Here are the clarified directions.

In your movieclip, place your graphic symbol at frame 1 pointing upwards (corresponding to '12' on the clock). Then, click on the graphic, right click and select Free Transform. There should now be some handles on the graphic that let you scale and transform the object. More importantly there will be a white dot in the middle of graphic. Click this dot and drag it to the pivot point of the hand (the end opposite to the pointing hand). This dot placement ensures that the graphic will rotate around this point.



Next, right click at frame 60, add a keyframe so that the same graphic should be shown at frame 60. Right click the frames in between and Create Motion Tween. The motion tween will be 60 frames long, but it can be longer given you modify the actionscript code that ensues. After creating the motion tween, in the motion tween properties, select CW rotation with 0 rotations. Next, you will need to select your endframe and rotate your pointer CCW by 6 degrees. You can do this by selecting the Align Window and clicking the Transform tab. We need to do this because, if we don't frame 1 and frame 60 will be at the same position, and will screw up the clock dynamics.

You will need to repeat this process for each of the three movie clips that animate each hand movement.

Now we take a look at the other parts of the clock. In another layer, create the face of the clock with the ticks and whatever else you want to add. Place this layer BELOW the main layer that will house your clock hands. It is a bit tricky to create the ticks on the clock but try to use the rotate function in Flash to rotate a circle with 1 tick 12 times, each time by 30 degrees.

Now on your main layer, place your three movie clips. Try to center them in the center of the clock face. Again, use the align function in Flash to help you with that. We will now name each animation with a instance name; we will name ours: minVar, hourVar, secVar.

Now in frame 1, we put in actionscript:

/:seconds=FSCommand2("GetTimeSeconds");
/:minWhole=FSCommand2("GetTimeMinutes");
/:hourWhole = FSCommand2("GetTimeHours");

The above three lines retrieve the values for the current hour, minute and second. Please note that the hour value is [0,23] format.

To make it easier to code, we will have to convert the 24-hour format to it's 12 hour equivalent. We will also designate AM/PM, by checking whether the returned hour value is greater or less than 12:

if(/:hourWhole>12){
if(/:hourWhole>11){

/:ampm = "PM";

}

/:hourWhole=/:hourWhole-12;

}else{

if(/:hourWhole==0){

/:hourWhole+=12;

}
/:ampm = "AM";
}

The next following lines compensate for fractions of an hour/minute, since the values returned above are whole numbers. For example, if it is 2:30, you want the hour hand to be between 2 and 3, not just at two:

/:hourFraction = (/:mins / 60)*5;

We multiply by 5 to yield a number between 1 and 60 (we will see why later).

/:minFraction = /:seconds/60;

Note that we do not need to calculate fractions for seconds, since it is a finite amount.

We then calculate the total number of hours and minutes by adding the remainder:

/:mins = int(/:minFraction + /:minWhole);
/:hours = int((/:hourWhole*5)+ /:hourFraction);

Now, /:mins is a variable between 0 and 60 (because there are sixty minutes in an hour). /:hours is also a variable between 0 and 60 because we multiplied hourWhole by 5, and hourFraction was multiplied by 5 in a few lines before this. We want /:hours in this format because our original animation had the hand rotating in sixty frames. Thus, we can use this number to refer to the frameNumber for which the time corresponds to.

*UPDATE: The following lines account for when the hour hand is at 12am and 12pm. It fixes the bug of not moving...

if(/:hours>60){
/:hours-=60;
}

*UPDATE: These blocks of code add the '0' in front of the minute or hour when it is a single display and is solely for display purposes. That's to say, it will say 9:05:01 instead 9:5:1.

if(/:minWhole<10){
/:minFormat = "0" add /:minWhole;
}else{
/:minFormat = /:minWhole;
}

if(/:seconds <10){
/:secondsFormat = "0" add /:seconds;
}else{
/:secondsFormat =/:seconds;
}


Here we use tellTarget() to tell the movieclips that are placed on the stage to go to their specific frame. Note that the movie clip contains frames 1-60, while any returned value will be between 0-59. This is why we add one to the variable:

tellTarget("secVar"){
gotoAndStop(/:seconds+1);
}
tellTarget("minVar"){
gotoAndStop(/:mins+1);
}
tellTarget("hourVar"){
gotoAndStop(/:hours+1);
}




Now in the main timeline, extend the frames such that the animation lasts 6 frames, lets say. This number is completely arbitrary and will vary depending your cellphone. Basically, you're determining the number of frames that pass after which the phone rechecks the time and updates the clock. Thus, an optimal frame duration would be one in which it updates at every second. But as we've seen with the frame rate profiles, frame rates run much slower on cellphones, so beware.

16 comments:

Anonymous said...

What a crap tutorial.... I don't understand it, you have to be clearer so less "into-flash" people can understand too....

FLT said...

If you can let me know which part you don't understand, then I can try to clarify things for you.

Anonymous said...

Sorry for my (rude) comment... Its creating the Pivot point and the 60 frames stuff.

FLT said...

I've rewritten that section with a new diagram and directions. Let me know if it is sufficient.

Anonymous said...

Hi.. Wonder what's in the Action Script at the beginning of frame 1 for the movie clip? Thks.

FLT said...

It is just a stop() command. Might not even be needed.

Anonymous said...

Thats much clearer :) Thanks for the tutorial!

VeraStefanija said...

Hi P.
I tryed this tutorial, but it simply does not work. I am begginer in Flash, so it is very possible I done something wrong, nedd to check one more time. Never the less gat some questions. Ergo, if all code is on frame 1 what code is on frame 6(on the main timeline), and what means "the hour value is 0.23 format"? Thanks

Unknown said...

Frame 6 has the code: gotoAndPlay(1);

Hour value of 0-23 means that the number returned from that function will be between 0-23 (as opposed to 1-12), where 0 represents 12 am, and 23 represents 11pm.

VeraStefanija said...

Understand.Thanks

VeraStefanija said...

Hi
It works but there is another problem to solve. Hope I can explane it right. Well, clock works perfectly untill 11.59 or 23.59. Than hour hand stands on position 11.59 for some time after 01.00, than jumps on right hour position. What is the problem?

FLT said...

Vera,

I've updated the tutorial to fix your problem and also added some formatting of the time for display. Hope this helps.

Anonymous said...

im a beginner with flash and i really want to make this clock work, but i don't seem to be doing it right. can you post a even more detailed tutorial ( somethig for dummies like me ) or maybe even a fla file. thank you.

Anonymous said...

Yes can you make a swf or fla file

Chris W said...

This tutorial was great -- I was able to use it to add clock functionality to my screensaver animation in less than half an hour. Many thanks!!!

Anonymous said...

a friend learned me the basics of flt 2 weeks ago... this doesn't matter
i thing it would be easyer in flt 2.0
with this:
it's a beta version

tellTarget("Sec"){gotoAndStop(fscommand2("GetTimeSeconds")+1)};
tellTarget("Min"){gotoAndStop(fscommand2("GetTimeMinutes")+1)};
tellTarget("Hour"){gotoAndStop(fscommand2("GetTimeHours")+1)}
seconds =FSCommand2("GetTimeSeconds");
if (Number(seconds<10)){seconds = "0" add seconds};
min =FSCommand2("GetTimeMinutes");
if (Number(min<10)){min = "0" add min};
hour24 =FSCommand2("GetTimeHours");
if(hour24>12){hour = hour24-12};
if(Number(hour<10)){hour = "0" add hour};