During this tutorial I will demonstrate how to make a custom timer which supports counting up or down to a specified amount of time.
Final Result PreviewIn the demo below you will see the time counting down from 1:00, a progress bar that tracks the progress of the timer and a cancel button.
Once the countdown from the 1:00 is finished, or you press the cancel button, a Movie Clip slides in from the right. This Movie Clip lets you enter a desired time, and determines whether you have the time counting up or down. A progress bar will then be attached and will track the progress of the time. Once the time completes, or you press the cancel button, you will be able to enter a new time.
Step 1: Coding the Custom Timer ClassHere we will write the custom timer class that will drive our main movie.
Go to File > New and Choose Actionscript 3.0 Class. Save this file as “CountTimer.as”.
Here we open the package and import the classes that we will need to write this class.
Add the following to the “CountTimer.as”
package{//Needed for the Timerimport flash.utils.Timer;import flash.events.TimerEvent;//We will update this TextField with the timeimport flash.text.TextField;Step 3: Variables and Constructor FunctionHere we will declare the variables the class will need, and code the constructor function.
Add the following to the “CountTimer.as”.
public class CountTimer extends Timer{//The textfield where the updated time goesprivate var targetText:TextField;//The direction of the timer i.e "up" or "down"private var direction:String;//How many minutes the timer hasprivate var minutes:int;//How many seconds the timer hasprivate var seconds:int;//Used in our calculation to update the timerprivate var totalSeconds:int;//The total amount of time = (Minutes+Seconds)private var timeTotal;//How much of the time has Passedprivate var timeLoaded = 0;//Set to true to test the timerprivate var test:Boolean = false;public function CountTimer(min:int,sec:int,dir:String,targetTextField:TextField=null){minutes = int(min * 60);seconds = int(sec);timeTotal = minutes + seconds;super(1000,timeTotal);if (dir == "down"){totalSeconds = minutes + seconds;}else{totalSeconds = 0;}if (targetTextField != null){targetText = targetTextField;}direction = dir;}Here we declared some variables we need for our class.
The Constructor Function takes four parameters; they are as follows:
min: An integer value that represents how many minutes you wish the timer to have.sec: An integer value that represents how many seconds you wish the timer to have.dir: A string representing the direction of the counter can be one of the following: “up” or “down”.targetTextField: A TextField that will be used to show the updated time (This is optional).Inside the constructor function we set the minutes variable equal to the specified value of min * 60 (since 1 minute is equal to 60 seconds).
We then set the seconds variable equal to the sec.
Next we set the timeTotal variable equal to minutes + seconds.
Then we call super() — which run the code from the constructor function of the Timer class — pass in 1000 milliseconds, and the timeTotal variable. By using 1000 milliseconds we tell the timer to tick one time each second, and by passing in timeTotal we tell the timer how many times to fire.
We next check whether the dir parameter is equal to “up” or “down” and set the totalSeconds variable accordingly.The total seconds will be used in our timeHandler() function. We will increment or decrement this by 1 each timer the timer fires off.
Then we check whether or not the user has passed in a TextField to the constructor and set the targetText variable if they did; this will be used to display the time.
Finally we set the direction variable to the direction the user passed in.
Step 4: Coding the start() FunctionHere we code the start() function for our timer.
Add the following the the to the “CountTimer.as”.
override public function start():void{super.start();addEventListener(TimerEvent.TIMER, timerHandler);}Because we extended Timer we are overriding the Timer’s existing start() method. Here we simply call super.start() (which runs the code from the Timer class’s start() method) and add an EventListener to detect when the timer ticks.
Step 5: Coding the timerHandler FunctionHere we code our timerHandler() function. This is where we update our time and display it. This function is called once every second.
Add the following to the CountTimer class.
private function timerHandler(e:TimerEvent):void{//Update our time Loaded variabletimeLoaded += 1;if (direction == "up"){//totalSeconds is = 0, to start with. We add 1 to it.totalSeconds++;}else{//totalSeconds = theNumber of seconds by adding min and sec; we subtract 1 from ittotalSeconds--;}//How may seconds there are left.seconds = totalSeconds % 60;//How many minutes are leftminutes = Math.floor(totalSeconds / 60);//The minutes and seconds to display in the TextField.var minutesDisplay:String = (minutes < 10) ? "0" + minutes.toString() : minutes.toString();var secondsDisplay:String = (seconds < 10) ? "0" + seconds.toString(): seconds.toString();if (targetText != null){targetText.text = minutesDisplay + ":" + secondsDisplay;}if (test=true){trace(minutesDisplay + ":" + secondsDisplay);}}Inside this function we update our timeLoaded variable, which is used to track the progress of how much time has passed.
Next we check whether direction is equal to “up” or “down” and adjust our totalSeconds variable accordingly.
We next determine how many seconds and minutes are left; pad the minutesDisplay and secondsDisplay with an extra zero if necessary; update the TextField (if one was passed into the constructor); and optionally trace out the time if we’ve set our test variable to true (handy for testing if you don’t set a TextField).
The calculation used to determine the seconds variable takes the remainder of totalSeconds/60.The % (modulo) operator gives us the remainder.
The calculation used to determine the minutes variable simply takes the totalSeconds/60, rounded down using Math.floor().
Step 6: Coding the getTimeTotal() FunctionHere we code a function that simply returns our timeTotal variable.Because we made this variable private we need a way to access it.
public function getTimeTotal():int{return timeTotal;}Step 7: Coding the getTimeLoaded() FunctionHere we code a function that returns our timeLoaded function. Once again because it is private we need a way to access it.
public function getTimeTotal():int{return timeTotal;}Step 8: Coding the getProg() FunctionThis function gives us the progress of our time.It is how much of the total time (that we set in the constructor) has passed. We multiply by 100 so we get a percentage between 1 and 100.
public function getProg():int{return Math.floor(timeLoaded/timeTotal*100);}Step 9: Testing the CountTimer ClassHere we begin to design the main movie that uses our “CountTimer” class.
Go to File > New and create a new ActionScript 3.0 document.
Set the size to 320x220px.
Save this document as “Timer.fla”. Go to File > New and choose Actionscript 3.0 Class.
Save this file as “Main.as”. We are going to test our CountTimer class,so add the following to the “Main.as”.
package{import flash.display.MovieClip;import CountTimer;public class Main extends MovieClip{var countTimer:CountTimer;public function Main(){countTimer = new CountTimer(1,30,"up");countTimer.start();} }}Make sure you set the test variable in “CountTimer.as” to true, and set the movie’s Document Class to “Main”.
Press ctrl-enter and test the movie; you should see the time traced in the Output window.
Step 10: Designing the User InterfaceHere we begin to design the main movie that uses our CountTimer class.
We will be using TweenLite in our movie so if you don’t have a copy get it from greensock.com.
Countdown/Countup TextSelect the Text tool and make sure the following properties are set in the “CHARACTER” Panel.
Size: 50.0 ptColor: BlackStill in the “Character” panel, click on “Embed” and make sure “UpperCase”,”LowerCase”,”Numerals” are selected, and under “Also include these characters”
that you have added a “:” and a “%”.
Draw a textfield out on the stage and set the following properties under the “POSITION and SIZE” Panel.
X: 0Y: 0W: 320H: 60Give this TextField the instance name “timer_txt”; make sure the type is set to “Classic Text” and “Dynamic Text” respectively.
This TextField will be used to show the time when the movie first Starts.
Progress BarNow we need to design our progress bar.
Go to Insert > New Symbol. Give it the name “ProgressContainer” and make sure “Export for Actionscript” is checked and that the Class is set to “ProgressContainer”.
Go to Window > Components and drag a ProgressBar component into the movie clip.
Set the ProgressBar’s properties to the following.
X: 0Y: 0W: 320H: 42.0Under “Component Parameters” set mode to “manual”.
Give the ProgressBar the instance name “pb”.
Select the Text tool and make sure the following properties under the “CHARACTER” Panel are set.
Size: 30ptColor: blackDraw a TextField into the movie clip.
Set the following properties on the TextField.
X: 80.0Y: 1.0W: 159.0H: 38:0Give this TextField the instance name “progress_txt”.
You can now close this MovieClip.
Growing and Fading TextNow we will design the growing and fading text, to be displayed when all the time has elapsed.
Go to Insert > New Symbol.Give it the name “GrowFadeText” and make sure “Export for Actionscript” is checked and the Class is set to “GrowFadeText”.
Select the Text tool and make sure following properties are set under the “Character” Panel.
Size: 15ptColor: [I set it to a blue, you can do the same if you wish]Drag out a TextField into the MovieClip and set the following properties.
X: -69.0Y: -6.35W: 135.0H: 21.0Enter the text “TIMER COMPLETE” into the textField. You can now close this MovieClip.
Entry FieldsNow we will design the MovieClip that slides in from the left. Select the rectangle tool and set the color to white. Drag out a rectangle from the top left of the stage to the bottom right.
Select the rectangle you just dragged out and press F8.Give it the name “countContainer”.Make sure “Export for Actionscript is checked and that Class is set to “countContainer”.
Set the following properties on the MovieClip.
X: 322Y: 0W: 320H: 220Now double click to go inside the MovieClip.
Select the Text tool and make sure the following properties are set in the “CHARACTER” Panel.
Size: 50ptColor: BlackDrag out a textfield onto the stage and set the following properties on it.
X: 0Y: 0W: 320H: 60Give this TextField the instance name “timer_txt” and make sure the type is set to “Classic Text” and “Input Text” respectively.
Once again select the Text tool and drag a TextField onto the stage.Then set the following properties on it.
X: 0Y: 59.0W: 320H: 60Give this TextField the instance name “instructions_txt” and make sure the type is set to “Classic Text” and “Input Text” respectively.
Go to Window > Components and drag three buttons inside this MovieClip.
Give the first button the instance name “countDown_btn” and set the following properties on it.
X: 14.00Y: 160Give the second button the instance name “cancel_btn” and set the following properties on it.
X: 103.00Y: 160.00Give the third button the instance name “countUp_btn” and set the following properties on it.
X: 182.00Y: 160.00You can now close the MovieClip.
Now that we have our UI Designed we can write the code for the main movie.
Step 11: Coding the Main MovieIf you are following along delete all the ActionScript in “Main.as” that you created in Step 9. That was for testing; now we need code that will work with our new interface.
Here we open the package declaration and import the classes we will be using.
Add the following to “Main.as”.
package{import flash.display.MovieClip;import fl.controls.Button;import flash.text.TextField;import flash.events.TimerEvent;import flash.events.MouseEvent;import flash.text.TextFieldType;import flash.text.TextFieldAutoSize;import CountTimer;import com.greensock.TweenLite;import flash.events.Event;import fl.controls.ProgressBar;Step 12: Variables and Constructor FunctionHere we declare our variables and code the Constructor.
Add the following the the “Main.as”
public class Main extends MovieClip{//An array to hold the minutes and seconds in elements [0] and [1]private var timeArray:Array;//Our countTimerprivate var countTimer:CountTimer;//A boolean that tells us whether this is the first timer//(the one used when the movie first starts)private var firstTimer:Boolean = true;//Direction of our timer can be "up" or "down"private var direction:String;//The MovieClip that contains the text we grow and fadeprivate var growFadeText:GrowFadeText;//The MovieClip that holds our progressBarprivate var progressContainer:ProgressContainer;//The minutesprivate var min:int;//The secondprivate var sec:int;public function Main(){min = 1;sec = 0;countTimer = new CountTimer(min,sec,"down",timer_txt);timer_txt.text = "1:00";countTimer.addEventListener(TimerEvent.TIMER_COMPLETE,timerComplete);setupButtons();addProgressContainer(0,70,"down");countTimer.start();stage.addEventListener(Event.ENTER_FRAME,updateProgress);cancel_btn.addEventListener(MouseEvent.CLICK,moveContainer);}First we set up the min and sec variables and pass them to the countTimer; we then set the direction to “down” and set the target TextField to timer_txt.
We then set some default text for the TextField,add an TIMER_COMPLETE event to the Timer, run a function to set up our buttons,add the ProgressBar,start the Timer, and add an ENTER_FRAME event listener to the stage (which we’ll use to update the progress bar), and finally add a CLICK event listener to our cancel_btn.
Step 13: Coding the timerComplete() FunctionAdd the following to “Main.as”.
private function timerComplete(e:TimerEvent):void{addGrowFadeText(154,130);if (firstTimer == true){TweenLite.to(growFadeText, 2.5, {scaleX:2, scaleY:2,alpha:0,onComplete:moveContainer});}else{TweenLite.to(growFadeText, 2.5, {scaleX:2, scaleY:2,alpha:0,onComplete:showTheControls});}}Here we add the text to the stage by calling addGrowFadeText() we will examine this function shortly.We then check the firstTimer variable to see if this is the first timer, if it is use tweenLite to grow and fade the text and call the moveContainer function once the animation completes.If it not the first timer then we once again use tweenLite to grow and fade the text but call the showTheControls() function once the animation completes.We will examine the moveContainer and showTheControls functions shortly.
Step 14: Coding the setupButtons() FunctionAdd the following to “Main.as”
private function setupButtons():void{countContainer.countDown_btn.addEventListener(MouseEvent.CLICK,doTimer);countContainer.countUp_btn.addEventListener(MouseEvent.CLICK,doTimer);countContainer.cancel_btn.addEventListener(MouseEvent.CLICK,restoreControls);countContainer.instructions_txt.text = "Enter time in format 1:30 then press CountDown or CountUp button";//We dont want user to be able to edit the textcountContainer.instructions_txt.selectable = false;}Here we add some EventListeners to our Buttons, set the text for our instructions_txt and set it so the user cannot select or edit the text. I used a TextField here to keep this already long tutorial shorter, but you would probably want to use a Label component here and style it with a TextFormat Object.
Step 15: Coding the addProgressContainer() FunctionAdd the following to “Main.as”
private function addProgressContainer(xPos:int,yPos:int,dir:String):void{progressContainer = new ProgressContainer();progressContainer.x = xPos;progressContainer.y = yPos;stage.addEventListener(Event.ENTER_FRAME,updateProgress);addChild(progressContainer);if (dir == "down"){progressContainer.pb.direction = "left";} else {progressContainer.pb.direction = "right";}}Here we create a new progressContainer and set its x and y properties by the xPos and yPos parameters that are passed in.We then add an ENTER_FRAME event listener that calls the updateProgress() function, and we add the progressContainer to the stage.Finally we check the dir parameter to see if it is equal to “down”; if it is we set the ProgressBar’s direction to “left”, otherwise we set the ProgressBar’s direction to “right”.
Step 16: Coding the removeProgressContainer() FunctionAdd the following to “Main.as”
private function removeProgressContainer():void{if (progressContainer != null){stage.removeEventListener(Event.ENTER_FRAME,updateProgress);removeChild(progressContainer);progressContainer = null;}}Here we check whether the progressContainer exists; if it doesn’t, then we remove the ENTER_FRAME event listener from the stage so it does not continue to run.We then remove the progressContainer from the stage and set it to null since we are done with it.
Step 17: Coding the updateProgress() FunctionAdd the following to “Main.as”.
private function updateProgress(e:Event):void{progressContainer.progress_txt.text = countTimer.getProg().toString() + "%";progressContainer.pb.setProgress(countTimer.getTimeLoaded(),countTimer.getTimeTotal());}Here we set the progress_txt‘s text to show the progress of our timer.We use the countTimer’s getProg() method which returns an integer of what percentage of the time has passed.Since it returns an int we use AS3's built in toString() method on it,and append a “%” sign to it.
Next we call the setProgress() method of the ProgressBar component on our ProgressBar (pb). We pass in countTimer.getTimeLoaded() and countTimer.getTimeTotal() which return integers. To learn more about the ProgressBar component check out my Quick Introduction to the ProgressBar component.
Step 18: Coding the addGrowFadeText() FunctionAdd the following to “Main.as”.
private function addGrowFadeText(xPos:int,yPos:int){growFadeText = new GrowFadeText();growFadeText.x = xPos;growFadeText.y = yPos;addChild(growFadeText);}Here we create a new instance of GrowFadeText, set its x and y properties as specified, and then we add it to the stage.
Step 19: Coding the removeGrowFadeText() FunctionAdd the following to “Main.as”.
private function removeGrowFadeText():void{if (growFadeText != null){removeChild(growFadeText);growFadeText = null;}}Here we check to see whether growFadeText exists. If it doesn’t, we remove it from the stage and set it to null.
Step 20: Coding the moveContainer() FunctionAdd the folowing to “Main.as”.
private function moveContainer(e:Event=null):void{countTimer.stop();removeChild(timer_txt);removeChild(cancel_btn);removeGrowFadeText();removeProgressContainer();countContainer.cancel_btn.visible = false;firstTimer = false;TweenLite.to(countContainer, 1, {x:0});}Here we stop the timer and remove the timer_txt and cancel_btn. Next we call our removeGrowFadeText() and removeProgressContainer() functions, set the cancel_btn within the countContainer to be invisible, set the firstTimer variable to false, and slide the countContainer in using TweenLite.
Step 21: Coding the showControls() FunctionAdd the following to “Main.as”:
private function showTheControls():void{showControls();removeProgressContainer();countTimer.stop();countContainer.timer_txt.text = "";countContainer.timer_txt.text = "";}Here we call the showControls function, which we will examine shortly. Next we call removeProgressContainer(), stop the timer and reset our TextFields to be blank.
Step 22: Coding the doTimer() FunctionAdd the following to “Main.as”:
private function doTimer(e:MouseEvent):void{if (e.target == countContainer.countDown_btn){direction = "down";}else{direction = "up";}if (countContainer.timer_txt.text != ""){timeArray = countContainer.timer_txt.text.split(":");min = timeArray[0];sec = timeArray[1];countTimer = new CountTimer(min,sec,direction,countContainer.timer_txt);countTimer.start();countTimer.addEventListener(TimerEvent.TIMER_COMPLETE,timerComplete);countTimer.addEventListener(TimerEvent.TIMER,updateProgress);hideControls();addProgressContainer(0,70,direction);}}We first check to see which button was pressed.If the countDown_btn was pressed we set the direction variable to “down” otherwise the we set the direction variable to “up”.Next we check to make sure timer_txt is not blank.If it is not then we use the split() function to put the minutes and seconds into the timeArray.The split() function takes a string and separates it by whatever you pass it as a parameter — here we used the colon (:) — and then adds each “piece” to the array. So, if you passed in "1:45", then the array’s element [0] would be “1?; element [1] would be “45?.
We then set the sec and min variables.
Next we create a new instance of the countTimer and pass in the min,sec,dir,and the TextField to use.
We then add two TimerEvent listeners that call our timerComplete() and updateProgress() functions.
Finally we call the hideControls() function and add the progressContainer to the stage.
Step 23: Coding the showControls() FunctionAdd the following to “Main.as”.
private function showControls():void{countContainer.instructions_txt.visible = true;countContainer.countDown_btn.visible = true;countContainer.countUp_btn.visible = true;countContainer.cancel_btn.visible = false;}Here we simply set the instruction_txt,countDown_btn,and countUp_btn to be visible. We then set the cancel_btn to be invisible.
Step 24: Coding the hideControls() FunctionAdd the following to “Main.as”.
private function hideControls():void{countContainer.instructions_txt.visible = false;countContainer.countDown_btn.visible = false;countContainer.countUp_btn.visible = false;countContainer.cancel_btn.visible = true;}This is the opposite of the previous function; here we just set the set the instruction_txt,countDown_btn,and countUp_btn to be invisible. We then set the cancel_btn to be visible.
Step 25: Coding the restoreControls() FunctionAdd the following to “Main.as”.
private function restoreControls(e:Event){showTheControls();countTimer.stop();}Here we call the showControls() function and stop the timer.
Step 26: Close the Class and Package.Add the following to “Main.as”
}//Close the Class}//Close the PackageHere we close out our class and package.
Step 27: Set the Document Class and Test the MovieAlthough not absolutely necessary,set the test variable to false in the “CountTimer”.as”.
Make sure your Document Class is set to “Main” and test the Movie.
ConclusionWe now have a versatile Timer Class that can be used for any number of things, from time limits on tests to setting times for levels on games.
I hope you found this tutorial useful and thanks for reading!
Tags: greensockinheritancestopwatchtimertweenlite Enjoyed this Post?Subscribe to our RSS Feed, Follow us on Twitter or simply recommend us to friends and colleagues!
TweetPlus Premium Hello!
You can grab source files and bonus tutorials from the members area.
Premium MembersSource Files, Bonus Tutorials & More for all relevant Tuts+ sites in one subscription. Join Now
Related PostsThats very impressive.
ReplyThanks I’ve always wanted to try some tricks with the timer function, this definitely will come in handy in my next flash project.
Reply Add a Comment Name Email Address URL Your Comments To add a code snippet to your comment, please wrap your code like so:YOUR CODE. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: < and > respectively. Click here to cancel reply. RSS Updates Email Updates Twitter Facebook RSS Subscribers 8,450 Twitter Followers 8,302 Facebook Fans 4,140 Advertise Here
Already a member? Sign In
Plus Icon Hello!Source Files, Bonus Tutorials & More for all relevant Tuts+ sites in one subscription
Members Area LogoutFollow Activetuts+ tech editor Michael James Williams as he walks you through integrating Flash with Facebook! Learn to develop apps for the Facebook website and harness the Graph API in your external projects.
Find Out More FacebookTwitter Follow Activetuts+ and Tuts+ on Twitter ? Create an Apple Inspired Flash Preloader http://enva.to/iYkBJSCheck out the great series of podcasts by @riaradio (now nerd radio) they did live at flash and the city http://ht.ly/5oR6DOur latest Fan Bonus tutorial is up on Facebook: http://j.mp/l6aBWP This one's about math tricks! ^MJW? Create a Complete Typing Game in Flash with AS3 http://enva.to/mGahuRGet weekly updates and an exclusive un-released tutorial when you sign up to our free newsletter.
Name Email Top Selling on ActivedenSagres Preta Chocolate - More
Freelance Jobs More Freelance Jobs... Basix Active BasixJust getting started? Start with our basix tutorials on the fundamentals. View All Basix Tutorials
Create a Tutorial, Get Paid!Have something to teach the world? Want to earn money doing it? Tutorials, screencasts, and articles published here on Activetuts+ are largely contributed by readers just like you! We'll pay you great money for good content. Find Out More
Activetuts+ Part of the Plus education network Powered by: Envato RSS Updates Email Updates Twitter Facebook Copyright © 2011 Envato Advertise Suggestions About Us Icons by WeFunction
No comments:
Post a Comment