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

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

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 running an event for a set duration after button (or anything) event

For the purposes of the question, Imagine I have an object onstage. When I click on another button, I want the colour to change for 1 second, then revert back again when finished.
Here's what my demo code looks like:
Button.addEventListener(MouseEvent.CLICK, Colour_Change);
function Colour_Change(evt: MouseEvent): void {
var my_color: ColorTransform = new ColorTransform();
my_color.color = 0xFF0000;
Coloured_Object.transform.colorTransform = my_color;
}
What I am wanting is some sort of timer function to be incorporated in the above function. I haven't got any idea how to do it, hence why there's no implementation.
You should use the flash.utils.Timer class.Adobe ActionScript 3.0 Reference for the Timer class
The following should be enough to get you headed in the right direction:
import flash.utils.Timer;
var myTimer:Timer = new Timer(1000, 1); // 1 second
var running:Boolean = false;
Button.addEventListener(MouseEvent.CLICK, Colour_Change);
myTimer.addEventListener(TimerEvent.TIMER, runOnce);
function Colour_Change(evt: MouseEvent): void {
var my_color: ColorTransform = new ColorTransform();
my_color.color = 0xFF0000;
Coloured_Object.transform.colorTransform = my_color;
if(!running) {
myTimer.start();
running = true;
}
}
function runOnce(event:TimerEvent):void {
// code to revert the button's color back goes here
myTimer.reset();
running = false;
}
Let me know if you need more help or if this example has errors via this answer's comments section.
To further explain the Timer class as used above:
when creating a new timer
myTimer=new Timer(1000,1)
the first number in the brackets is the number of milliseconds you want the timer to run for (e.g. 1000 = 1 second)
The second number is how many times you want the timer to repeat (or 0 for infinite repetition).
Every time the timer reaches the time you entered (1000), this is will trigger any event listeners for the event Timer_Event.TIMER, so for example if u wanted to make it change color on and off, you could have multiple repetitions on the timer and change the function.
Other useful things timers can do:
You can add an event listener for
Timer_Event.TIMER_COMPLETE
(goes off when all repetitions are complete)
myTimer.currentCount
will return the number of repetitions the timer has done so far.
To do that you can use, as other answers said, a Timer object or the setTimeout() function, like this :
// the current color of our target object
var default_color:ColorTransform;
// the delay in milliseconds
var delay:int = 1000;
btn.addEventListener(MouseEvent.CLICK, Colour_Change);
function Colour_Change(evt: MouseEvent): void {
// save the current color of our target object
default_color = target.transform.colorTransform;
var new_color:ColorTransform = new ColorTransform();
new_color.color = 0xFF0000;
target.transform.colorTransform = new_color;
var timer:Timer = new Timer(delay, 1);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
// after the delay, we use the default color of our target
target.transform.colorTransform = default_color;
})
timer.start();
// using setTimeout(), you have to disable this if using the Timer
var timeout:int = setTimeout(
function(){
clearTimeout(timeout);
// after the delay, we use the default color of our target
target.transform.colorTransform = default_color;
},
delay
);
}
Hope that can help.

Ajusting as3 code to trigger on mouse event

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.

How to Increase a timer AS3

Hey everyone cant really figure out the easiest approach to this problem.
Basically I have a timer that starts in the beginning of the game like so:
//Create new timer object
tEggTimer = new Timer (nTimerSpeed);
//Listen for timer intervals
tEggTimer.addEventListener(TimerEvent.TIMER, addEggs, false, 0, true);
//start timer
tEggTimer.start();
The nTimerSpeed is equal to (800);
Then I add the eggs like so:
private function addEggs(e:TimerEvent):void
{
//var eggGlobalPosition:Point = _Egg.localToGlobal(new Point(_Bunny.x, _Bunny.y));
_Egg = new mcEgg();
stage.addChild(_Egg);
_Egg.x = _Bunny.x;
_Egg.y = _Bunny.y + 30;
aEggArray.push(_Egg);
trace(aEggArray.length);
}
So in another enter frame function I want to change the value of the timer to (500), but whenever I try like so:
tEggTimer = new Timer (500);
tEggTimer.start();
like So:
private function updateDifficulty():void
{
if (difficultyUpdate) return;
if (nScore >= 2)
{
tEggTimer.removeEventListener(TimerEvent.TIMER, addEggs);
tEggTimer.stop();
tEggTimer = new Timer(200);
tEggTimer.addEventListener(TimerEvent.TIMER, addEggs);
tEggTimer.start();
But this doesnt do anything but stop the timer entirely.
What can I do in order to decrease the timer correctly?
Thanks guys.
If you just want to change the timer speed, while keeping everything else the same, you could just change the delay property in the timer object.
Sample here:
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
var speeds:Vector.<int> = new <int>[1000, 2000, 5000];
var currentSpeed:int = 0;
var timer:Timer = new Timer(speeds[currentSpeed]);
function timerTick(inputEvent:TimerEvent):void {
trace("Timer ticking: "+ getTimer());
}
timer.addEventListener(TimerEvent.TIMER, timerTick, false, 0, true);
timer.start();
function clickedStage(inputEvent:MouseEvent):void {
currentSpeed = ++currentSpeed % speeds.length;
timer.delay = speeds[currentSpeed];
trace("Timer delay set to "+ timer.delay);
}
this.stage.addEventListener(MouseEvent.CLICK, clickedStage, false, 0, true);
Clicking on the stage will change the timer delay from 1 second, 2 seconds, 5 seconds and cycle. I'm just using getTimer() to show the rate of which the timer is ticking.
Note that it seems from the output, every time the value is changed, the timer will automatically restart.
timer.reset();
timer.delay = 2000;
timer.start();
May no be the best way but, instead using nTimerSpeed, make it run through every millisecond:
tEggTimer = new Timer (1);
Then in your AddEggs function use nTimerSpeed and a counter variable. counter is initialize to 0. Incase all your logic in an if statement, increment counter every time through function. if counter equals nTimerSpeed, allow for them inside the if statement and reset counter.
function AddEggs()
{
if(counter == nTimerSpeed)
{
//adding eggs logic
counter = 0;
}
counter++;
}
Did you try saying: tEggTimer.stop() just before re-instantiating with the 500 ms version? I'm guessing that your first Timer instance will just keep firing as your new one starts, unless you deliberately stop it.

How to reduce the timer's time while timer is running (ActionScript 3.0)

In my case, the timer I make doesn't reduce its time whenever a function is called. What code will I change or add in order to reduce the time in my timer?
Timer code:
var count:Number = 1200;
var lessTime:Number = 180;
var totalSecondsLeft:Number = 0;
var timer:Timer = new Timer(1000, count);
timer.addEventListener(TimerEvent.TIMER, countdown);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timesup);
function countdown(event:TimerEvent) {
totalSecondsLeft = count - timer.currentCount;
this.mainmc.time_txt.text = timeFormat(totalSecondsLeft);
}
function timeFormat(seconds:int):String {
var minutes:int;
var sMinutes:String;
var sSeconds:String;
if(seconds > 59) {
minutes = Math.floor(seconds / 60);
sMinutes = String(minutes);
sSeconds = String(seconds % 60);
} else {
sMinutes = "";
sSeconds = String(seconds);
}
if(sSeconds.length == 1) {
sSeconds = "0" + sSeconds;
}
return sMinutes + ":" + sSeconds;
}
function timesup(e:TimerEvent):void {
gotoAndPlay(14);
}
At this point the timer.start(); is placed on a frame so that the timer starts as it enters the frame.
The delay property on Timer is what you are looking for. In your handler, change the timer's delay:
function countdown(event:TimerEvent)
{
totalSecondsLeft = count - timer.currentCount;
this.mainmc.time_txt.text = timeFormat(totalSecondsLeft);
//change the timer delay
timer.delay -= lessTime;
}
I assumed by your code sample that you wanted to subtract lessTime from the timer delay on each timer interval. If you want to change the delay to something else, then just adjust the code accordingly.
UPDATE
The above code is for decreasing the interval (delay) between each timer fire. If what you'd like to do instead is decrease the the amount of intervals (repeatCount) it takes for the timer to reach TIMER_COMPLETE, then you want to change the repeatCount property on Timer:
//set the timer fire interval to 1 second (1000 milliseconds)
//and the total timer time to 1200 seconds (1200 repeatCount)
var timer:Timer = new Timer(1000, 1200);
//reduce the overall timer length by 3 minutes
timer.repeatCount -= 300;
ANOTHER UPDATE
Keep in mind that when you alter the repeatCount, it doesn't affect the currentCount. Since you are using a separate count variable and timer.currentCount to calculate the displayed time remaining, it doesn't look like anything is changing. It actually is though - the timer will complete before the displayed time counts down to zero. To keep your time left display accurate, make sure to subtract the same amount from count as you are from repeatCount:
timer.repeatCount -= 300;
count -= 300;