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;
}
}
Related
I am trying to program a Phidgets device to repeatedly turn an external light on for .5 sec and off for .5 sec.
(these times correspond to Frames 1 and 11 of a 20 frame movie clip.
I've tried to insert the on- and off- commands into the movie clip, but they don't transfer to the main stage, so now I'm just trying to program the light to go on and off from the main program
The code below turns the light on and off at the SAME TIME- which means NOTHING HAPPENS.
Does anyone know how to delay the timer so that the off command comes 500 msec AFTER the on command ?
THanks
phid.addEventListener(PhidgetEvent.ATTACH,onAttach);
//connects Phidget to software
function onAttach(evt:PhidgetEvent):void{
trace(evt);
}
var phidControl:Timer = new Timer (500);
phidControl.addEventListener(TimerEvent.TIMER, lightOn);
function lightOn (evt:TimerEvent):void {
phid.setOutputState(0, true);} //this turns the light on
enter code here
var phidOff:Timer = new Timer(500);
phidControl.addEventListener(TimerEvent.TIMER, lightOff);
function lightOff(evt:TimerEvent):void {
phid.setOutputState(0, false);//this turns light off
}
it looks like you're creating two Timers which both run at a 500ms interval simultaneously.
It might be easier to put one function on a 500ms timer, which will call either function intermittently, something like
var lightIsOn = false;
function lightToggle(evt:TimerEvent):void{
if(lightIsOn){
lightOff();
}else{
lightOn();
}
lightIsOn = !lightIsOn;
}
---- UPDATE ----
I'm not very familiar with Phidgets, however that shouldn't make a difference in this case. Try this:
val = true;
var phidControl:Timer = new Timer(500); //If you don't set the repeat count it goes on forever
phidControl.addEventListener(TimerEvent.TIMER, lightToggle);
function lightToggle(evt:TimerEvent):void {
val = !val;
phid.setOutputState(0,val);
}
phidControl.start(); //Make sure you start the timer.
If you only want to switch it once every .5 seconds then you don't have to worry about reading the state of the light, just tell it when to change. So from what I can tell, you don't need the inputChange function.
What I want to do is:
After colliding with an [object], I want the screen to flash for about half of a second. I have tried for loops and while loops but they seem to not work. I have no idea how I should program this.
I've been trying to figure out how to do this since I'v been making the game so it would be helpful if someone could help me.
Thank you for reading.
You need to use something that involves time. loops all run in a thread which doesn't pause for time - which is why they don't work.
Here is how you could do this with an AS3 Timer (let's say this code runs right after you've determined there's been a collision)
function flashScreen():void {
var timer:Timer = new Timer(50, 10); //run the timer every 50 milliseconds, 10 times (eg the whole timer will run for half a second giving you a tick 10 times)
var flash:Shape = new Shape(); //a white rectangle to cover the whole screen.
flash.graphics.beginFill(0xFFFFFF);
flash.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
flash.visible = false;
stage.addChild(flash);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
//we've told AS3 to run this every 50 milliseconds
flash.visible = !flash.visible; //toggle visibility
//if(Timer(e.currentTarget).currentCount % 2 == 0){ } //or you could use this as a fancy way to do something every other tick
});
timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(e:TimerEvent):void {
//the timer has run 10 times, let's stop this flashing madness.
stage.removeChild(flash);
});
timer.start();
}
Other ways you can do this are with setInterval, setTimeout, a Tweening library,and an ENTER_FRAME event handler.
I'm making a game where the reaction time to killing an enemy is shown and used in later calculations. The number needs to be precise and in seconds, with three significant figures. So i need the current value of a timer to be converted to a numerical value.
I have it so the enemy spawns, a timer (reactionTimer) event begins and when it's killed a variable (reactionTime) will be set to the reactionTimer.
a new one then spawns and it resets the timer and variable.
I've had a few tries at it but it always ends up showing the timer value as either "Object Timer" or 0.
I've also tried using currentCount but this doesn't give me decimal numbers and just works oddly.
New ActionScript developers often mix up the purpose of the Timer class and TimerEvent. It's really for triggering actions at a specific time, not for measuring time.
For measuring time, you use the getTimer function. Whenever you call it, it returns the number of milliseconds that have elapsed since Flash player started. To measure an elapsed time you just call getTimer() twice and subtract the first measurement from the second.
There are a lot of ways you could organize your particular situation. One would be to store the spawn timestamp of the enemy right on the enemy class, capturing it the constructor:
public class Enemy extends MovieClip {
public function get spawnTime():int { return _spawnTime; }
private var _spawnTime:int;
// Constructor
public function Enemy() {
super();
_spawnTime = getTimer();
}
}
Then when enemy is killed you call getTimer() again to get the reaction time:
// Somewhere, where you are processing the enemy killed event
var killTime:int = getTimer();
var reactionTime:int = killTime - killedEnemy.spawnTime; // in whole ms
var reactionSeconds:Number = reactionTime / 1000; // in seconds
I'm trying to make a dice game in Flash/ActioScript 3. I did all the essentials and it works smoothly. Now I want to improve the user experience. For instance, when it's computer's turn (to roll and do things according to die value) I want to animate the die. The die has 6 keyframes. So, for, say, 2 seconds the die will loop those 6 frames then it will stop on a value (depending on random generator). Somehow I can't do it as I want. How can I write a function(s) so that when I say,
animateDice()
it will do nothing but just animate the dice for a specified interval?
Update:
var timer:Timer = new Timer(10, 50);
myButton.addEventListener(MouseEvent.CLICK, onClick);
timer.addEventListener(TimerEvent.TIMER, animateDice);
function onClick(event: Event):void {
timer.start();
}
function animateDice(event: Event):void {
dice.play();
}
For instance, I don't understand why the above code doesn't work properly. It does work properly on first click, but not there after.
Update 2: I guess I'm still having problems. How do I suspend the running code until the timer stops? (Yes there is a work around---putting timer handlers inside other timers, etc. Is there an easy way?
Maybe, this will help:
First we see the die rolling (and a message box informs the user that the game will decide whom starts). Then it's either Human's or Computer's turn. When it's computer's turn, first we see the rolling die again for, say, 1 second. Then it stops and and we see the outcome. I'm a beginner and I nay be missing something, but from what I see it seems that all these simple steps (just showing the die rolling for some time) means lots and lots of lines.
If I use a simple timer for die animation, the script continues and the whole show goes away.
The timer object has three properties:
delay, or how often the event should fire
repeatCount, or how many times the event should fire
currentCount, or how many times the timer's event has fired thus far
You are creating the timer with new Timer(10, 50), which sets delay to 10 and repeatCount to 50. This means that, once you call timer.start(), timer will fire TimerEvent.TIMER every 10 milliseconds. Each time it is fired, it adds 1 to currentCount. When currentCount is greater than or equal to repeatCount (50), it stops looping the timer.
Once your timer has stopped, if you call timer.start() again, it will only fire the event once, because currentCount has not been reset to zero, and is still >= repeatCount.
If you call timer.reset() before calling timer.start(), it will set this value to zero and things should behave as expected.
var timer:Timer = new Timer(2000, 1);
myButton.addEventListener(MouseEvent.CLICK, onClick);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
function onClick(event: Event):void {
timer.reset();
timer.start();
dice.play();
}
function onTimerComplete(event:TimerEvent):void {
var roll:int = int(Math.floor(Math.rand()*6))+1;
dice.gotoAndStop(roll);
}
The timer is set to run only once, for 2000 milliseconds (which are 2 seconds). When Click occurs, the timer is reset (so that if it's not the first time it was clicked, it will run as if it was the first time) and started, and the animation starts a well. After 2 seconds, TIMER_COMPLETE will be fired by the timer, and we catch it and determine a final number for the die, then gotoAndStop to that frame.
I didn't try to compile the code, but the gist of it should work for you.
P.S, dice is the plural of 'die' :) you're skipping a great opportunity for the type of variable names we all want to use but can't!
You could try something a little more like this:
var t:Timer = new Timer(10, 50);
t.addEventListener(TimerEvent.TIMER, timerHandler);
t.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler);
t.start();
function timerHandler(e:TimerEvent):void {
gotoRandomFrame();
}
private function timerCompleteHandler(e:TimerEvent):void {
var finalNum:int = gotoRandomFrame();
// Using finalNum
}
private function gotoRandomFrame():int {
var num:int = Math.floor(Math.random() * 6) +1;
dice.gotoAndStop(num);
return num;
}
So use gotoAndStop to set your frame rather than using play
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();