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;
}
Related
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.
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.
Im doing a little game in actionscript, and i have a timer that starts when the gamer starts and end when the game ends.
But i want to show in a textfield the value of my timer during the game like 1,2,3,4,5,6, etc.
How can i can acess that timer propriety to get the value?
My timer code is this:
startTime = (new Date().time);
endTime = (new Date().time);
public function testTime():void
{
const 5_min = 5 * 60 * 1000;
const 2_min = 2 * 60 * 1000;
var timeDiff:Number = endTime - startTime;
if (timeDiff < 2_min) {
trace("Good!");
} else {
trace("Bad!");
}
}
And here (above) i create a txt field. Now, how i can show the timer value while playing the game?
var timer_txt:TextField;
pontuacao = new TextField();
timeDiff = 0;
timer_txt = new TextField();
timer_txt.text = String(timeDiff);
stage.addChild(timer_txt);
timer_txt.x = 470;
timer_txt.y = 320;
Well, first of all, in AS you cannot begin your variable names with a number, therefore this code should absolutely not compile (5_min, 2_min = WRONG!).
You have your startTime, which is ok. Now you will have to check the current time in some kind of event (Timer, EnterFrame) or interval (setInterval) and update the endTime value accordingly. Once you have it, you just count the difference and divide it by 1000 (I assume you don't want to show it in millis)
Something like this:
import flash.utils.setInterval;
var s:Number = new Date().getTime(); //start time
var e:Number; //end time
var d:Number; //difference
setInterval(function () {
e = new Date().getTime();
var oldDiff:Number = d;
d = int((e - s) / 1000);
if(oldDiff != d) trace(d + " seconds since launch");
},
100
);
I'm creating app and I need to show game time MM:SS format. But I don't know why timer doesn't wrok It shows 0:00.359 (359 of miliseconds) and not change. Where is the problem? I can't find It. Thank you.
var timer:Timer; //import flash.utils.Timer;
var txtTime:TextField;
var tmpTime:Number; //this will store the time when the game is started
//your constructor:
public function MemoryGame()
{
timer = new Timer(1000); //create a new timer that ticks every second.
timer.addEventListener(TimerEvent.TIMER, tick, false, 0, true); //listen for the timer tick
txtTime = new TextField();
addChild(txtTime);
tmpTime = flash.utils.getTimer();
timer.start(); //start the timer
//....the rest of your code
}
private function tick(e:Event):void {
txtTime.text = showTimePassed(flash.utils.getTimer() - tmpTime);
}
//this function will format your time like a stopwatch
function showTimePassed(startTime:int):String {
var leadingZeroMS:String = ""; //how many leading 0's to put in front of the miliseconds
var leadingZeroS:String = ""; //how many leading 0's to put in front of the seconds
var time = getTimer() - startTime; //this gets the amount of miliseconds elapsed
var miliseconds = (time % 1000); // modulus (%) gives you the remainder after dividing,
if (miliseconds < 10) { //if less than two digits, add a leading 0
leadingZeroMS = "0";
}
var seconds = Math.floor((time / 1000) % 60); //this gets the amount of seconds
if (seconds < 10) { //if seconds are less than two digits, add the leading zero
leadingZeroS = "0";
}
var minutes = Math.floor( (time / (60 * 1000) ) ); //60 seconds times 1000 miliseocnds gets the minutes
return minutes + ":" + leadingZeroS + seconds + "." + leadingZeroMS + miliseconds;
}
//in your you-win block of code:
var score = flash.utils.getTimer() - tmpTime; //this store how many milliseconds it took them to complete the game.
Try
timer.currentCount
instead of
flash.utils.getTimer()
It will return the number of times the timer has fired the TIMER-Event.
You need not do this.
var time = getTimer() - startTime;
In your code, startTime is already time elapsed due to
showTimePassed(flash.utils.getTimer() - tmpTime);
OR
you can call
showTimePassed();
and change time calculation as
var time = getTimer() - tmpTime;
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