How to call a function at specified date time? - actionscript-3

I want to call a method at 23:55 of the day,
how to do this in actionscript 3?

I'd say you create a loop that checks the current time throught the Date Object.
package {
import flash.display.Sprite;
import flash.utils.clearInterval;
import flash.utils.setInterval;
public class TimeCheck extends Sprite
{
private var interval:int;
public function TimeCheck()
{
interval = setInterval( checkTime, 1000 );//check performed every second
checkTime();
}
private function checkTime():void
{
var date:Date = new Date();
if ( date.hours == 23 && date.minutes == 55 )//actual time check
{
clearInterval( interval );//kills the loop
//... do something ...
}
}
}
}
note that this is executed client-side so the client time will be used. there may be a way to sync it to a server time though.
hope it helps

AS3 has timeouts (e.g. setTimout) like JavaScript. The use of setTimeout in AS is talked about here. Given the two dates (now and when the alarm should trigger), compute the difference in milliseconds and use it as the timeout parameter.
Alternatively (and ever so much less efficiently, but not enough to bat an eye over), setTimeout could be run every minute and if it is the "magical time" (or past it when the previous interval was before!, remember need 2x the frequency to observe all changes and a clock-shift could occur...) then sound the alarm.
Note that there are some limitations like the AS host being closed during the timeout period or clock shifts. Likely no DST to worry about here, but daylight-savings issues do come up when dealing with dates/times.
Happy coding.
Edit: AS also has the Timer class which is an wrapper for setTimeout/setInterval/clearTimeout/clearInterval functionality. In any case, if "working with objects" is preferred.

I haven't tested it but something like this should work...
var eventDate:Date = new Date();
eventDate.setHours( 23, 55 );
var now:Date = new Date();
var delay:Number = eventDate.time - now.time;
if( delay > 0 )//if we haven't yet passed 23:55
{
var timer:Timer = new Timer( delay , 1 );
timer.addEventListener( TimerEvent.TIMER , yourMethod );
timer.start();
}

I believe the above solutions work; however, they appear to be very costly in terms of performance. I have a two-liner that is (relatively) elegant and straight-forward. The solution uses an anonymous function, client-side time, and assumes you are given a parameter, startDate:Date. I have not tested this, so there might be a simple logic error, but the idea should give someone ideas.
var timer:Timer = (new Timer(startDate.time - (new Date()).time, 1)).addEventListener(TimerEvent.TIMER, function():void {
// This area is called after the allocated time.
});
timer.start();

Related

Timer, SetInterval, Alarm, etc

Help turning multiple functions into a a few functions.
var myNumberOne = 10;
var myNumberTwo = 100;
function one would create a timer or interval that fire 2 times every second, Traceing the word "food", It would when finished, "myNumberOne += 10" making myNumberOne = 20;
function two would create a timer or interval that fire 5 times every half-second, Traceing the word "ben", It would when finished, "myNumberTwo += 50" making myNumberTwo = 250;
For two functions this is fine, but if I have 100s of possible combinations, I cannot think on this should be done, without intervals , timers, functions etc... interfering with each-other, and passing arguments through time.
Thanks for any help.
for clarification: I waant to call a function like this
setTimeFunction("myTimeOne", myNumberOne, 2,1000,10, "ben");
setTimeFunction("myTimeTwo", myNumberTwo, 5,500,50,"food");
Well, first, you need to compose a generic method that would perform a number of similar actions. Tracing is easy, but you cannot pass a variable to change directly because you'll pass a value, not a reference to variable. In order to do as you want you need to pass it as a pair "container object" and "variable name" to use the square bracket notation.
function myownDothings(target:Object, varname:String, adiff:int, totrace:String):void
{
// Use square bracket notation to change the targeted variable.
target[varname] += adiff;
// Trace the given argument.
trace(totrace);
}
Ok, now the simple complicated part. There's a setTimeout(...) function that calls the given method many times with a given timeout, but it's official documentation officially advises the use of Timer class.
I hope you know how to work with classes, because the thing you want calls for OOP and fitting it into the frame scripts will result in something ugly. So, you need to compose a class that remembers function to call, timeout settings and a bunch of arguments as well.
package
{
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Ticker
{
// You need to keep the references to the things you use,
// or else Garbage Collector might think you don't need it.
static private var list:Array = new Array;
// Instead of static method you can use the "constructor" way,
// but I find it more stylish and it's one more thing for
// you to google and learn of, which I totally approve.
// The ... construction allows to pass a random number
// of arguments (after fixed arguments) as an Array.
static public function create(handler:Function, timeout:int, ...args:Array):void
{
var aTicker:Ticker;
// Brackets () are not mandatory with the "new" operator
// if there are no mandatory constructor arguments.
aTicker = new Ticker;
// Store all the necessary data in the new instance. That's the
// point of OOP scripting here: you want to make 100 different
// tickers and you need each of them to keep some custom data.
aTicker.timeout = timeout;
aTicker.handler = handler;
aTicker.args = args;
// Finally, run the ticker.
aTicker.start();
// Store the created instance into the keeper list
// to prevent Garbage Collector from destroying it.
list.push(aTicker);
}
// Again, fear the Garbage Collector.
private var clock:Timer;
// Keep in mind that timeout is not exactly accurate
// as it aligns to the SWF's frame rate. Setting it up to call
// more times a second than FPS will pose to be a meaningless act.
private var timeout:int;
// The reference to the method to call.
private var handler:Function;
// The list of arguments to pass to the method above.
private var args:Array;
// This method is called from the "create" method
// to finalize things and start ticking.
private function start():void
{
// Create a Timer instance with a given timeout.
clock = new Timer(timeout);
// Subscribe the listener to the Timer.
clock.addEventListener(TimerEvent.TIMER, onTick);
// Start the Timer.
clock.start();
}
// The Timer instance will trigger this method
// (approximately) every given timeout of milliseconds.
private function onTick(e:TimerEvent):void
{
// Now the idea is to call the given method
// passing the list of given arguments to it.
// Normally you don't need to pass the "this" object
// to a method unless you use unnamed unbound closures.
// (which I personally consider a heresy and don't recommend to use)
// So you just pass "null" as the first argument and everything is fine.
handler.apply(null, args);
}
}
}
Now, the usage. It's where all the horrors above finally shine.
import Ticker;
var myNumberOne = 10;
var myNumberTwo = 100;
// Fire 2 times every second, increase "myNumberOne" by 10, trace the word "ben".
// So, 2 times a second it will call: myownDothings(this, "myNumberOne", 10, "ben");
Ticker.create(myownDothings, 1000 / 2, this, "myNumberOne", 10, "ben");
// Fire 5 times every half a second, increase "myNumberTwo" by 50, trace the word "food".
// So, 10 times a second it will call: myownDothings(this, "myNumberTwo", 50, "food");
Ticker.create(myownDothings, 500 / 5, this, "myNumberTwo", 50, "food");

Timer reset after 20 seconds but calling a function randomly AS3

At the moment I am putting together a timer that is supposed to add a movieclip to the stage at a random moment within 20 seconds, but it has to count a full 20 seconds and then reset.
Now like this I can make the timer countdown for a random time up to a maximum of 20 seconds, but it repeats right after that random time. So I was thinking of a Timer delay of 20000 - whatever time the randommath + 20000 has produced. However I can't think of a way to reference the produced time.
Anybody out there who knows of a way to accomplish this? Or maybe a workaround with another method?
Thanks in advance!
var treasureclip:MovieClip= new xClip;
var treasureTimer = new Timer(Math.random() * 20000);
treasureTimer.addEventListener("timer", placeTreasure);
treasureTimer.start();
function placeTreasure(evt:TimerEvent):void {
addChild(treasureclip);
Timer(evt.currentTarget).delay = 20000 - //something
}
import flash.utils.setTimeout;
var treasureclip:MovieClip= new xClip;
/*to check it adds movieClip uncomment this and comment previous
var treasureclip:MovieClip= new MovieClip;
with(treasureclip.graphics)
{
beginFill(0);
drawRect(0,0,50,50);
}*/
var timeout:uint;
startTimeout();
setInterval(startTimeout, 20000);
function startTimeout():void
{
timeout = setTimeout(placeTreasure, int(20000 * Math.random()));
}
function placeTreasure():void {
addChild(treasureclip);
}
//Don't forget to kill timeout with clearTimeout(timeout) to avoid memory leaks

Calling and removing instances of a timer

In my code, I utilize two timers:
var timerScroll:Timer = new Timer();
var timerCollission:Timer = new Timer();
First of all... how do I actually call timerScroll/timerCollission to get it's current value...
and for later on...
how do I reset or remove the timer instance from either of them so I can start anew?
I've tried doing like timerScroll.getTimer();... and timerScroll.flash.utils.getTimer();... which I figured wasn't going to work but tried it anyways =D
Use a timer like this:
var timerScroll:Timer = new Timer( 2000 ); //2000ms = 2 second interval
timerScroll.start();
timerScroll.stop();
timerScroll.reset();
Then, in a separate event listener, apply your callback function to the TIMER event.
timerScroll.addEventListener(TimerEvent.TIMER, myCallback);
function myCallback(e:TimerEvent) {
trace( timerScroll.currentCount() );
}
See the API docs here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html

Timer in Starling Framework

Hello everybody I am developing a game with starling and i want to set a timer for example every 2 sec i want something to happen.
I used the juggler elapsed prop but i wonder is there a more effecient way to do that
thank you,
Khaled
Alternatively, you can use the "DelayedCall" class. It's easy to miss! ;-)
var delayedCall:DelayedCall = new DelayedCall(method, 2.0);
delayedCall.repeatCount = int.MAX_VALUE;
Starling.juggler.add(delayedCall);
function method():void
{
trace("ping");
}
If this does not relate to animation, it is recommended to use a Timer for non-animated content.
Timer implementation would be higher performance than additional time calculations on enter frame handler.
If you are advancing Starling Jugglers, you can set the frame rate of the Juggler to every 2-seconds.
Jugglers also have delayCall in which you could infinitely loop every 2-seconds if your functor redundantly called delayCall:
juggler.delayCall(functor, 2.0);
To tie in to Starlings frame / render lifecycle, you can test time since your last call.
private var lastCallTime:int
protected function frameHandler():void
{
var now:int = getTimer();
var ellapsed:int = now - lastCallTime;
if(ellapsed >= 2000)
{
/* execute implementation */
lastCallTime = now;
}
}

Accurate BPM event listener in AS3

I'm trying to sync animation to music at a specific BPM. I've tried using the Timer but it isn't accurate when dealing with small intervals in milliseconds. I did some reading and found an alternate method that uses a small silent audio file and the SOUND_COMPLETE event as a Timer.
I used 167ms long sound file with this code.
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
public class BetterTimer extends EventDispatcher
{
private var silentSound:Sound;
public function BetterTimer(silentSoundUrl:String):void {
super();
silentSound = new Sound( new URLRequest(silentSoundUrl) );
silentSound.addEventListener(Event.COMPLETE, start);
}
public function start():void {
this.timerFired( new Event("start") );
}
private function timerFired(e:Event):void {
dispatchEvent( new Event("fire") );
var channel:SoundChannel = silentSound.play();
channel.addEventListener(Event.SOUND_COMPLETE, timerFired, false, 0, true);
}
}
}
This still doesn't stay on beat. Is the Flash Player capable of accuracy with sound?
You can also use the new Sound API with the SampleDataEvent and basically play your MP3 manually using Sound.extract(). In that case you know the latency up front and can even count up to the sample when your (delayed) event should happen.
This is what we do in the AudioTool and it works very well.
This is very tricky to get right! There's a small lib called BeatTimer that tries to do this. I haven't tried this code myself, but if it does what it claims it should be exactly what you need.
Setting the frame rate so that the event interval is a multiple of the frame rate might help (for example, 167ms equals 6 fps; 12, 18, 24 etc. are then also ok).
If I understood correctly, better solution would be to use the enterframe event. Instead of determining the position of the animation by counting the events, calculate it using elapsed time (getTimer or sound position). This would also make the animation work on slower computers that have lag.
I was looking through the popforge library's AudioBuffer and tried using one of the approach. That's the create a sync sound. The following is what i did.
var syncSamples:ByteArray = new ByteArray();
syncSamples.length = (2646000 / _bpm) << 1; /*44100*60=2646000*/
SoundFactory.fromByteArray(syncSamples, Audio.MONO, Audio.BIT16, Audio.RATE44100, soundInit);
The ms delay is pretty close, eg: at 120 BPM, it's between 509 - 512ms. The question is, am I going in the right direction?