Adding additional time to main timer from movieclip? - actionscript-3

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.

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.

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.

Problems with adding and subtracting time from/to Timers

Now I am also using a timer in frame 8, which is my Gamescreen frame to try and create an energy bar, so decreasing by 1 every second, and everytime the character collides with an object then increment the value of count by 1 (which in my min is 1sec, right?), however the timer runs out prematurely, when the label is showing 3secs left after collecting 3 items the timer automatically ends, HELP ME! :)
var count:Number = 5; (temporary value for testing)
var theTimer:Timer = new Timer(1000, count);
theTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
theTimer.start();
function whenTimerComplete(e:TimerEvent):void
{
theTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, whenTimerComplete); //Remove listener
gotoAndStop("frameFive"); // Advance to score screen.
}
theTimer.addEventListener(TimerEvent.TIMER, theCountdown);
function theCountdown(e:TimerEvent):void
{
count--;
timerLabel.text = count.toString()
}
//Start the timer and show in the label.
timerLabel.text=count.toString();
theTimer.start();
All help and a solution is VERY much appreciated.
Here's an example countdown timer:
Launch Flash example
FLA source code
Countdown Timer AS3 source code
CS6 ZIP of source code
CS5 ZIP of source code
Create a countdown timer class at the root of your FLA:
CountdownTimer.as
package {
import flash.events.TimerEvent;
import flash.utils.Timer;
public class CountdownTimer extends Timer {
public var time:Number = 0;
public function CountdownTimer(time:Number = Number.NEGATIVE_INFINITY, delay:Number = 1000) {
super(delay, repeatCount);
if (!isNaN(time))
this.time = time;
repeatCount = Math.ceil(time / delay);
addEventListener(TimerEvent.TIMER, timerHandler);
}
protected function timerHandler(event:TimerEvent):void {
time -= delay;
if (time == 0)
dispatchEvent(new TimerEvent(TimerEvent.TIMER_COMPLETE));
}
public function dispose():void {
removeEventListener(TimerEvent.TIMER, timerHandler);
}
}
}
On the timeline of your FLA, create a timer with the total number of milliseconds to countdown:
var timer:CountdownTimer = new CountdownTimer(60000);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler);
timer.start();
In the example above, the timer will countdown for 1-minute (60-seconds). Each second the timerHandler will be called. When it reaches 0, the timerCompleteHandler will be called.
function timerHandler(event:TimerEvent):void {
timerText.text = (timer.time / 1000).toString();
}
function timerCompleteHandler(event:TimerEvent):void {
timerText.text = "COMPLETE";
}
To add time to the timer, add milliseconds to time. If you want the timer to dispatch timer complete event when it reaches 0, update the repeatCount:
timer.time += 1000;
timer.repeatCount += 1;
Likewise to remove time from the timer, subtract milliseconds from time; and again, if you want the timer to dispatch timer complete event when it reaches 0, update the repeatCount:
timer.time -= 1000;
timer.repeatCount -= 1;

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 add seconds to Timer in AS3

Hey everyone So I have a countdown timer that I have managed to implement in my game that I saw on some forums. Now I set up a new function to add some seconds to the timer whenever the user Hittest with a Movie Clip but it doesnt seem to work right the errors I'm getting is while it does add more time, It's not really adding it because when i do add more time and say the timer counts down to 10 depending on how much more seconds I added with the Hittest the game ends on 10 rather than 0 seconds. So I don't think its actually changing the time interval internally.
Also when I restart the game it shows the past time for the one second interval then once it starts counting down it finally resets and starts counting down normally.
Here is how I have it setup:
My initialized variables in my constructor:
count = 30; //Count down from 60
myTimer = new Timer(1000, count);// Timer intervall in ms
myTimer.addEventListener(TimerEvent.TIMER, countdown);//EventListener for intervalls
myTimer.addEventListener(TimerEvent.TIMER_COMPLETE, countdownComplete);
myTimer.start();//start Timer
The countDown function:
private function countdown(e:TimerEvent):void
{
//Display Time in a textfield on stage
countDownTextField.text = String((count)- myTimer.currentCount);
updateCountdownTimer();
}
In my HitTest Function:
private function onPopIsClicked(pop:DisplayObject):void
{
nScore ++;
updateHighScore();
updateCurrentScore();
//Add Explosion Effect
popExplode = new mcPopExplode();
stage.addChild(popExplode);
popExplode.y = mPop.y;
popExplode.x = mPop.x;
elapsedTime += 5;
updateCountdownTimer();
}
Then finally in my updateCountdownTimer():
public function updateCountdownTimer():void
{
countDownTextField.text = String((count)- myTimer.currentCount + elapsedTime);
}
Can you see why I can't add more seconds to the timer correctly?
Thanks in advance.
**** UPDATE ******
count = 10; //Count down from 10
myTimer = new Timer(1000, count);// Timer intervall in ms
updateCountdownTimer();
myTimer.addEventListener(TimerEvent.TIMER, countdown);//EventListener for intervalls
myTimer.addEventListener(TimerEvent.TIMER_COMPLETE, countdownComplete);
myTimer.start();//start Timer
private function countdown(e:TimerEvent):void
{
//Display Time in a textfield on stage
updateCountdownTimer();
}
private function onPopIsClicked(pop:DisplayObject):void
{
elapsedTime += 2;
myTimer.repeatCount += elapsedTime; //add time to the timer
count += elapsedTime;
updateCountdownTimer();
trace("pop clicked and time");
}
public function updateCountdownTimer():void
{
countDownTextField.text = String((count)- myTimer.currentCount);
}
So the solution to add time to the Timer is to adjust the repeatCount property. You would do that in your onPopIsClicked():
private function onPopIsClicked(pop:DisplayObject):void
{
nScore ++;
updateHighScore();
updateCurrentScore();
//Add Explosion Effect
popExplode = new mcPopExplode();
stage.addChild(popExplode);
popExplode.y = mPop.y;
popExplode.x = mPop.x;
elapsedTime += 5;
myTimer.repeatCount += 5; //add time to the timer
updateCountdownTimer();
}
So you will need to change how you display your countdown since we are increasing the repeatCount property. What will happen is your myTimer.currentCount may increase past the size of your count variable. So in your onPopIsClicked() add this line after you increment elapsedTime:
elapsedTime += 5;
myTimer.repeatCount += 5;
count += 5//this line, increment the count total
You can also set a variable to increment by if you wanted:
var increaseBy:int = 5
Then you would use that with repeatCount, count, and elapsedTime (if you need that still):
elapsedTime += increaseBy;
myTimer.repeatCount += increaseBy;
count += increaseBy;
You really don't need elapsedTime anymore unless you are using it for something else. Then you update your text, there is no need to add the elapsedTime so it would look like:
countDownTextField.text = String(count- myTimer.currentCount);