Ajusting as3 code to trigger on mouse event - actionscript-3

Hi I found this really useful code for a timer counter, however it starts when I play the file. What I need is a way to change this into a MouseEvent.CLICK so it starts when the user presses a button and it stops when the uses presses another button. Is this do able?
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.globalization.DateTimeFormatter;
var timer:Timer = new Timer(100);
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerTickHandler);
var timerCount:int = 0;
function timerTickHandler(Event:TimerEvent):void
{
timerCount += 100;
toTimeCode(timerCount);
}
function toTimeCode(milliseconds:int) : void {
//create a date object using the elapsed milliseconds
var time:Date = new Date(milliseconds);
//define minutes/seconds/mseconds
var hours:String = String(time.hours);
var minutes:String = String(time.minutes);
var seconds:String = String(time.seconds);
var miliseconds:String = String(Math.round(time.milliseconds)/100);
//add zero if neccecary, for example: 2:3.5 becomes 02:03.5
hours = (hours.length != 2) ? '0'+hours : hours;
minutes = (minutes.length != 2) ? '0'+minutes : minutes;
seconds = (seconds.length != 2) ? '0'+seconds : seconds;
//display elapsed time on in a textfield on stage
timer_txt.text = hours + ":" + minutes + ":" + seconds+"." + miliseconds;
}

The easiest thing to do would be to use timer.stop() and timer.start(). This won't be perfectly accurate, as calling stop() and start() basically restarts the current delay (100ms), but if that's good enough then it should work.
Also note that the timer code isn't perfectly accurate as is, since Timer events are dispatched with slight offsets based on framerate and script execution time. For an accurate timer you need to poll getTimer(), but pausing and resuming becomes a little more complicated to implement.

Related

Error 1009-handling

I want to make counterdown in quiz. In my quiz, after endtime it will go to another frame. The time is about 10 minutes, exactly. In this code I just write in 31 second to make it simple.
This is my code
import flash.events.*;
import flash.utils.Timer;
import flash.utils.getTimer;
stop()
var totSec:int = 31;
var totTime:Number = 1000 * totSec;
var secTimer:Timer = new Timer(1000,totSec);
secTimer.start ();
secTimer.addEventListener (TimerEvent.TIMER, updateClock);
function updateClock (t:TimerEvent) {
var timePassed:int = totTime - getTimer();
var second:int = Math.floor(timePassed/1000);
var minute:int = Math.floor(second/60);
//trace ("second : " + second);
second %= 60;
var sec:String = "";
sec = String(second);
if (second < 10)
{
sec = "0" + second;
}
var showTime:String = minute + " : " + sec;
timeDisplay.text = String(showTime)
if (minute == 0 && second == 0 )
{
gotoAndPlay(525);
//addEventListener (Event.ENTER_FRAME, stopTime);
trace ("Times up");
secTimer.start ();
}
}
But, when the frame go to frame 525, I get this error
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at adminserver/updateClock()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
The issue:
Your timer actually ticks one more time after you do the following:
gotoAndPlay(525);
//addEventListener (Event.ENTER_FRAME, stopTime);
trace ("Times up");
secTimer.start(); <---------not sure what this is about?
So when it ticks again, you've actually gone to a different frame (525) where your timeDisplay text field no longer exists (presumably) - so the code errors.
when you change frames, code attached to listeners keeps running even if that code wasn't on the current frame
The Cleanest Solution
Instead of doing your own math to figure out when the timer is done, use the actual timer event for such:
secTimer.addEventListener(TimerEvent.TIMER_COMPLETE, .....
This way, you know the timer is done before your code runs and you change frames.
Here is a full example, along with some tips:
stop();
var totSec:int = 31;
//no need for this var, total time in your case is secTimer.repeatCount * secTimer.delay
//var totTime:Number = 1000 * totSec;
var secTimer:Timer = new Timer(1000,totSec);
secTimer.addEventListener(TimerEvent.TIMER, updateClock);
//listen for the complete event when the timer is all done
secTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timerComplete);
secTimer.start();
function updateClock (e:TimerEvent) {
//the timer's currentCount will be how many times the timer has ticked,
//which in this case will be seconds elapsed.
//If you subtract that from the total repeat count, you'll get the seconds left,
//no need to use getTimer, which is now allows you to pause your timer if you'd like (can't pause using getTimer)
var second:int = secTimer.repeatCount - secTimer.currentCount;
var minute:int = Math.floor(second/60);
//trace ("second : " + second);
second %= 60;
var sec:String = String(second);
if (second < 10){
sec = "0" + second;
}
var showTime:String = minute + " : " + sec;
timeDisplay.text = String(showTime);
}
function timerComplete(e:TimerEvent):void {
trace ("Times up");
//secTimer.start(); //you don't really want to start the timer again - which does nothing anyway without a secTimer.reset() first
//you should also remove the listeners on the timer so it can freed for garbage collection
secTimer.removeEventListener(TimerEvent.TIMER, updateClock);
secTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, timerComplete);
gotoAndPlay(525);
}
I think that to avoid that error, you should stop that Timer before going to another frame :
// ...
trace ("Times up");
secTimer.stop();
gotoAndPlay(525);
// ...
Hope that can help.

AS3 How to Set Up A Max Time Count Up

I have the following count up code, but am not sure how I would be able to include an if else statement to have the count-up stop at 15 seconds for example.
Here is the code:
var timer:Timer = new Timer(100);
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerTickHandler);
var timerCount:int = 0;
function timerTickHandler(Event:TimerEvent):void{
timerCount += 100;
toTimeCode(timerCount);
}
function toTimeCode(milliseconds:int) : void {
//create a date object using the elapsed milliseconds
var time:Date = new Date(milliseconds);
//define minutes/seconds/mseconds
var minutes:String = String(time.minutes);
var seconds:String = String(time.seconds);
var miliseconds:String = String(Math.round(time.milliseconds)/100);
//add zero if neccecary, for example: 2:3.5 becomes 02:03.5
minutes = (minutes.length != 2) ? '0'+minutes : minutes;
seconds = (seconds.length != 2) ? '0'+seconds : seconds;
//display elapsed time on in a textfield on stage
timer_txt.text = minutes + ":" + seconds+"." + miliseconds;
}
First, for efficiency, you can use the timers built in currentCount property to know how much time has elapsed (instead of making a timerCount var to that end)
To stop the timer after 15 seconds, simply set the appropriate repeat count so it ends at 15 seconds, or stop it in the tick handler after 15 seconds have past:
var timer:Timer = new Timer(100,150); //adding the second parameter (repeat count), will make the timer run 150 times, which at 100ms will be 15 seconds.
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerTickHandler);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerFinished); //if you want to call a function when all done
function timerTickHandler(Event:TimerEvent):void{
toTimeCode(timer.delay * timer.currentCount); //the gives you the amount of time past
//if you weren't using the TIMER_COMPLETE listener and a repeat count of 150, you can do this:
if(timer.delay * timer.currentCount >= 15000){
timer.stop();
//do something now that your timer is done
}
}

Adding additional time to main timer from movieclip?

Hi so yeah in the main timeline I have the timer
var count:Number = 300;//Count down from 300
var myTimer:Timer = new Timer(1000,count);
myTimer.addEventListener(TimerEvent.TIMER, sayHello);
function sayHello(e:TimerEvent):void
{
trace("Current Count: " + myTimer.currentCount);
}
And when you go into the movieclip reimoi_mcand click the useplush button I want to be able to add additional seconds onto the timer. The following is the code in the reimoi_mc clip but yeah I really have no idea how to make this work, please help ;0; (I have to use MovieClip(root) to access the running timer from the main timeline within the movieclip)
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.utils.getTimer;
stop();
useplush.addEventListener(MouseEvent.CLICK, addtime);
function addtime(e:MouseEvent):void
{
MovieClip(root).count += 2;
MovieClip(root).myTimer.repeatCount += MovieClip(root).count; //add time to the timer
trace("new time " + myTimer.currentCount);
}
I think what you are trying to do is add 2 seconds to the timer in the click handler, and then show how much time is left? If so, just a couple tweaks will do:
function sayHello(e:TimerEvent):void {
trace("Time Left: " + myTimer.repeatCount - myTimer.currentCount); //time left is the repeat count - the current count
}
function addtime(e:MouseEvent):void {
MovieClip(root).myTimer.repeatCount += 2 //add 2 more ticks to the timer (currentCount will always remain the same unless the timer is reset)
trace("new time remaining: " + MovieClip(root).myTimer.repeatCount - MovieClip(root).myTimer.currentCount);
}
BONUS CODE!
If you wanted to make it agnostic of the timer delay (let's say you want it to update quicker than 1 second for instance), you could do this:
var startingTime:Number = 20; //the initial time in seconds
var myTimer:Timer = new Timer(200); //your timer and how often to have it tick (let's say 5 times a second)
myTimer.repeatCount = startingTime * Math.ceil(1000 / myTimer.delay); //set the initial repeat count
myTimer.addEventListener(TimerEvent.TIMER, sayHello);
myTimer.start();
function sayHello(e:Event):void {
trace("Time Left: " + ((((myTimer.repeatCount - myTimer.currentCount) * myTimer.delay) / 1000)) + "seconds");
}
And in your other object:
stage.addEventListener(MouseEvent.CLICK, function(e:Event){
myTimer.repeatCount += Math.ceil(2000 / myTimer.delay); //add 2000 milliseconds to the timer
});
You'd better use an external counter to count the time, instead of stuffing it into a Timer object. You would then need timers to measure delays, and listeners to count them.
var myTimer:Timer=new Timer(1000); // no second parameter
public var secondsLeft:int=300; // former "count"
myTimer.addEventListener(TimerEvent.TIMER, sayHello);
function sayHello(e:TimerEvent):void {
secondsLeft--;
trace("Seconds left:", secondsLeft);
if (secondsLeft<=0) {
myTimer.stop();
myTimer.reset();
// whatever else to trigger when time runs out
}
}
And then you just add to secondsLeft and update the scoreboard.

calculate minutes left between hours actionscript 3

I'm using AS3 to pull XML data, one field is a time field in the XML and displays an hour. I'm getting the date and then the AS3 loads the proper node based on teh time set in the XML. This is all working perfect - I have two times as variables, one is the system time (which is set in UTC time) the other is one hour ahead.
The two variables are currentHour and newHour - it's doing everything I want however I'd like to now create a countdown between these two hours and display time remaining in the minutes.
Here is the complete code for that.
Get the time from XML using AS3
These seems straight forward but I'm having a hard time. I've tried this:
var data:Array = [currentHour, newHour];
var aDate:String = data[0].split(" ")[0];
var dateElements:Array = aDate.split("-");
var date1:Date = new Date();
date1.setMinutes(int(data[0].split(" ")[1].split(":")[0]));
dateElements = data[1].split(" ")[0].split("-");
var date2:Date = new Date();
date2.setMinutes(int(data[1].split(" ")[1]));
var elapse:Number = date2.getTime() - date1.getTime();
trace("minutes: " + date2.getMinutes());
But that isn't right, so I tried this:
if(currentHour < newHour)
{
var dayDiff:Number = newHour-currentHour;
// make sure it’s in the future
if (dayDiff > 0)
{
var seconds:Number = dayDiff / 1000;
var minutes:Number = seconds / 60;
}
trace(minutes, seconds);
}
If someone could help me get unstuck that would be amazing. Thank you!
Created a new answer which didn't contain the spam from previous one where I tried to figure out what the actual issue was and what the expectations of the program was. Anyways to summarize:
User wanted to, given a specific date/time, find out how long until the next complete hour, so for instance given the time 4:47pm wanted to find out how many minutes and seconds left until 5:00pm.
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.globalization.NumberFormatter;
import flash.utils.getTimer;
import flash.utils.Timer;
var timer:Timer = new Timer(250);
var my_date:Date = new Date();
var targetDate:Date = new Date();
//calculate how many total milliseconds left until next whole hour since that is how as3 is using Date-objects
var timeUntilWholeHourMS:Number = (60 - my_date.getMinutes()) * 60 * 1000;
targetDate.setTime(my_date.getTime() + timeUntilWholeHourMS);
//clear the "second and milliseconds" part of the new time since we want the whole hours
targetDate.setSeconds(0, 0);
var secondsLeft:Number = (targetDate.time - new Date().time) / 1000;
//make sure it is in the future
if (secondsLeft > 0) {
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
function onTimer(e:flash.events.TimerEvent):void {
secondsLeft = (targetDate.time - new Date().time)/1000;
if (secondsLeft > 0) {
var minutes:Number = Math.floor(secondsLeft/60);
var seconds:Number = Math.floor(secondsLeft%60);
trace("minutes left: " + minutes, ", seconds left: " + seconds);
} else {
//time limit reached
timer.removeEventListener(TimerEvent.TIMER, onTimer);
timer.stop();
trace("Time limit reached!");
}
}
I'd reccomend you using Timer. At first declare a variable seconds (between currentHour and newHour):
private var seconds:int;
Then assign it value
seconds = (newHour - currentHour) * 3600;
Then declare a timer which will tick every second (second parameter tells how much times will it tick):
var timer:Timer = new Timer(1000, seconds)
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
And then create timerHandler that will make all necessary updates:
function func(e:TimerEvent):void {
--seconds;
//if you have some textfield that shows minutes left, update it's text here
//timeTextfieldText.text = int(seconds / 60) + " minutes left";
trace(int(seconds / 60));
}
A bit unclear on how you want to present the data, but this is how to get it working at least. You need to replace "currentHour & newHour" with actual hours. And then handle the cases inside onTimer with approriate code.
The thing that differentiates this code towards the other solutions are that this takes a timestamp when you start and then whenever a timer event occurs it will check the current time against that timestamp. Meaning it doesn't matter if the flash timer is off by a couple of milliseconds etc.
import flash.events.TimerEvent;
import flash.globalization.NumberFormatter;
import flash.utils.getTimer;
import flash.utils.Timer;
var timer:Timer = new Timer(250);
var currentHour:Number = 14;
var newHour:Number = 15;
var totalSeconds:Number = 0;
var timestampStart:Number = 0;
if(currentHour < newHour) {
totalSeconds = (newHour - currentHour) * 3600;
if (totalSeconds > 0) {
timestampStart = getTimer();
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
}
function onTimer(e:flash.events.TimerEvent):void {
var secondsRunning:Number = (getTimer() - timestampStart) / 1000;
var secondsLeft:Number = totalSeconds - secondsRunning;
if (secondsLeft > 0) {
var minutes:Number = Math.floor(secondsLeft/60);
var seconds:Number = Math.floor(secondsLeft%60);
trace("minutes left: " + minutes, ", seconds left: " + seconds);
} else {
//time limit reached
timer.removeEventListener(TimerEvent.TIMER, onTimer);
timer.stop();
trace("Time limit reached!");
}
}
You need to add an enterFrame event hanler
private var frameCount:int = 0;
private var diff:int = 3600;//the seconds between the two hours, you could set it here
this.addEventListener(Event.ENTER_FRAME, handler);
private function handler(event:Event):void {
frameCount++;
if (frameCount >= stage.frameRate) {
frameCount = 0;
diff--;
if (diff < 0) {
this.removeEventListener(Event.ENTER_FRAME, handler);
}
}
var minutes:int = diff/60;
}

How do you stop setInterval() after certain number of iterations

I have tried following code and its working but how do i stop when its reach 130 ?
var textValue:Number = 67.1;
var addValue:Number = .1;
my_txt.text = textValue.toString();
function counter(){
textValue += addValue;
my_txt.text = textValue.toString();
}
setInterval(counter, 10);
setInterval returns a unique ID as an unsigned int (uint). You can use clearInterval with this ID to stop the interval. The code:
var textValue:Number = 67.1;
var addValue:Number = .1;
var myInterval:uint;
function counter(){
textValue += addValue;
my_txt.text = textValue.toString();
if( textValue >= 130 ) {
clearInterval(myInterval);
}
}
myInterval = setInterval( counter, 10 );
You can stop an interval by using clearInterval. Try this:
var textValue:Number = 67.1;
var addValue:Number = .1;
my_txt.text = textValue.toString();
function counter(){
textValue += addValue;
my_txt.text = textValue.toString();
//check for end value
if (textValue>=130)
{
//clear the interval
clearInterval(intervalID);
}
}
//store the interval id for later
var intervalID:uint = setInterval(counter, 10);
Since it seems like you may be using actionscript 3, I suggest not using an interval at all. A Timer object may be better as it can offer better control, such being able to set the number of times it fires off before stopping itself and being able to easily start, stop, and restart the timer as needed.
Example of using a Timer object and adding an event listener for each tick
import flash.utils.Timer;
import flash.events.TimerEvent;
// each tick delay is set to 1000ms and it'll repeat 12 times
var timer:Timer = new Timer(1000, 12);
function timerTick(inputEvent:TimerEvent):void {
trace("timer ticked");
// some timer properties that can be accessed (at any time)
trace(timer.delay); // the tick delay, editable during a tick
trace(timer.repeatCount); // repeat count, editable during a tick
trace(timer.currentCount); // current timer tick count;
trace(timer.running); // a boolean to show if it is running or not
}
timer.addEventListener(TimerEvent.TIMER, timerTick, false, 0, true);
Controlling the timer:
timer.start(); // start the timer
timer.stop(); // stop the timer
timer.reset(); // resets the timer
Two events it throws:
TimerEvent.TIMER // occurs when one 'tick' of the timer has gone (1000 ms in the example)
TimerEvent.TIMER_COMPLETE // occurs when all ticks of the timer have gone (when each tick has happened 11 times in the example)
API Documentation: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html