In my cards game, I'm trying to simulate the opponent to think about his choice. During this time I want to let appear on the screen a thinking cloud... this is possible with the command TCloud.visible = true; and false to let it disappear. After the think time (5 seconds) I want some more seconds ( like 2-3 seconds) so you can see what the opponent has decided, and then start again... I've already written the logic part of the actions, just need you to help me with this problem.
You have to use the Timer class and do something like this:
// create a timer that dispatch an event after 3 seconds
private function wait3seconds():void {
var timer:Timer = new Timer(3000, 1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
timer.start();
}
private function onTimerComplete(event:TimerEvent):void {
// do something
}
Related
I have a big issue with my code
I have a function called "delayCallFuntions":
function delayCallFuntions(delay: int, func: Function) {
var timer: Timer = new Timer(delay, 1);
timer.addEventListener(TimerEvent.TIMER, func);
timer.start();
}
And I used this function like below to make connection between 2 point in my screen:
delayCallFuntions(1, function (e: Event) {timer011(wireColor);});
And function "timer011" is making the connections:
function timer011(firstColor: int): void {
wireColor = firstColor;
//GRID is a class
//Path A to B
var PathAB: Grid;
PathAB = new Grid(4, 5, 20, 17, canvas, wireColor);
this.addChild(PathAB);
}
My problem is:
I have several of these functions like "timer012", "timer013", ... that they need to execute one after another.
When I go out of this scene and come back again, these is still some of these functions are working while I need them to start from the beginning and go one by one.
for example: when i come back, "timer011" is starting while "timer016" is also completing at the same time.
hope someone can help me as this problem made me frustrated.
Currently you are creating a whole new timer everytime you add a function. That timer will stay in memory because of the event listener, and since it's encapsulated in the function, you have no easy way to reference it again to stop them.
What would be a better approach, is to create just one timer globally referenced so you can stop it if needed.
Here is a way you could accomplish this:
//create an array that will hold all the functions you are planning on calling
var delayedFuncs:Array = [];
//this var will be used to store the current function that will be called next
var currentFuncObj:Object = null; //set it to null so it clears the value when you return to this frame
//create a single, global timer reference for everything
//don't initialize it here though
//if you revisit this frame, you don't want to create a whole new timer, but keep using the previous one
var funcTimer:Timer;
//if the timer has already been created (you've been to this frame before), stop it
if (funcTimer) {
funcTimer.stop();
}else {
//if you haven't been to this frame before, create the timer and add the listener
funcTimer = new Timer(1,1);
funcTimer.addEventListener(TimerEvent.TIMER, nextFunc, false, 0, true);
}
//this function adds items to your queue. I've added the ability to also include parameters
function delayCallFunctions(delay:int, func:Function, ... funcParams):void {
//add an object to the array that stores the function, delay, and any parameters to pass to that function
delayedFuncs.push({delay: delay, func: func, params: funcParams});
//if the timer hasn't started running yet, start it since we've added something
if(!funcTimer.running) nextFunc();
}
//this function runs when the timer completes
function nextFunc(e:Event = null):void {
//if we have an existing function to call, call it
if (currentFuncObj){
//invoke the function with the parameters
currentFuncObj.func.apply(null, currentFuncObj.params);
}
//if there are still items in the array, grab the next one
if(delayedFuncs.length > 0){
//array.shift grabs the first element in the array and removes it from the array
currentFuncObj = delayedFuncs.shift();
//reset the timer
funcTimer.reset();
//set the appropriate delay
funcTimer.delay = currentFuncObj.delay;
//start the timer again
funcTimer.start();
}
}
So now, you'd use by doing:
delayCallFunctions(3000, trace, "hello", "world", "I'll be traced 3 seconds from now");
delayCallFunctions(2000, trace, "I'll be called 2 seconds after the last one");
Or, with your specific code:
delayCallFuntions(1000, timer011, wireColor);
Now at any time (say you hit a button to go to change scenes), you can just stop the global timer.
funcTimer.stop();
I'm making a simple helicopter game to try and get into making flash games. I wanted to make a countdown timer that will count down from 3 seconds, then start the loop, but I'm not sure how to go about is. I don't use the frames in flash, rather I use action script (3) to make an "ENTER_FRAME" loop, if that helps. It looks like this:
addEventListener(Event.ENTER_FRAME, mainLoop);
I'm sure I need to put the timer above it, I'm just not sure how to make a timer. Any advice will probably help, as I'm new to AS3, thanks.
To make a countdown timer, you can use a Timer, like this :
trace('3');
// create a timer with : delay: 1 second, repeats: 3
var timer:Timer = new Timer(1000, 3);
timer.addEventListener(
TimerEvent.TIMER,
// on every repeat
function(e:TimerEvent):void {
trace(Math.abs(timer.currentCount - 3)); // gives : 2, 1, 0
}
)
timer.addEventListener(
TimerEvent.TIMER_COMPLETE,
// at the timer end
function(e:TimerEvent):void {
// do other instructions
trace('go');
}
)
// start the timer
timer.start();
Hope that can help.
I hope i can help you with your code. What im getting is that you try to make 3 seconds count down then start somewhere.
yes you need a timer :
var theTime:Timer
theTime = new Timer(countDownLoading*1000); //1000 is in milisecond
var countDown = 1;
var totalCountDown = 3; // How long it'g gonna count
var countDownLap = totalLoading;
theTime.addEventListener(TimerEvent.TIMER,tick); //adding timer event
function tick(e:TimerEvent){
if(countDownLap == 0)//if the cound down is 0
{
time.stop();
gotoAndStop(2);
trace("Finish counting");
} else { //not counting down yet, then lets count
countDownLap = countDownLap - countDown; //
trace(countDownLap);
}
//timer goes like the ticking clock so if the count down is not 0.
//everytime the ticking starts the cound down (3) - 1
}
I hope this help.
I'm building a memory Flash game, in which there's a timer that gives you a certain amount of time to finish the deck of cards. The code for this timer is shown below:
public function memory():void
{
levelDuration = 10;
gameTime = levelDuration;
var gameTimer:Timer = new Timer(1000,levelDuration);
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired);
gameTimer.start();
}
function updateTime(e:TimerEvent):void // what happens when the time runs out
{
// your class variable tracking each second,
gameTime--;
//update your user interface as needed
timeText.text = "Tijd : " + String(gameTime); //gameTime is defined before the public function memory
}
function timeExpired(e:TimerEvent):void
{
var gameTimer:Timer = e.target as Timer;
gameTimer.removeEventListener(TimerEvent.TIMER, updateTime);
gameTimer.removeEventListener(TimerEvent.TIMER, timeExpired);
finalScore = score;
musicchannel.stop();
gameTimer.stop();
MovieClip(root).gotoAndStop("gameover");
}
Now, this works fine. The timer counts down, and when it expires, it brings you to the gameover screen. However, when you finish the game BEFORE the time expires, the timer doesn't stop. It will bring you back to the gameover screen when it decides it has run out, even when you've started a new game.
I've tried to fix this by putting gameTimer.stop() in other functions that bring you to the gameover screen, but then there was another problem. This occurred while trying to stop the timer in other functions, like this one (stop button while playing):
function stopplaying(event:MouseEvent){
gameTimer.stop();
finalScore = score;
musicchannel.stop();
MovieClip(root).gotoAndStop("introduction");
}
This will give me a compile error 1120: access of undefined property gameTimer.
I understand that the gameTimer usually can only be influenced within a function if that function listens to a TimerEvent, but I don't see any options to do this in any other way.
I've tried to make gameTimer a public variable, but it won't allow me to do that within the main memory function.
Also, when I try to define it a public variable out of a funcion, but within the class, the timer will still count down. But when it expires, it just gives a random high number in return and doesn't go to the gameover screen.
I hope the explanation of my problem wasn't too vague and that you are able to help me with this. This is a schoolproject and it's due pretty soon! Also, I can't figure this out on my own with internet alone :( Several tries have only made things worse, I'm afraid to screw this up now that I've come this far.
You were doing it probably right-ish by declaring it as a public variable.. but where did you declare it?
In AS (all versions) you have function scope. That means if you declare your variable inside a function, that variable "exists" (is accessible) only inside of that function. Check where you are declaring your variable:
public function memory():void
{
levelDuration = 10;
gameTime = levelDuration;
var gameTimer:Timer = new Timer(1000,levelDuration); // <-
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired);
gameTimer.start();
}
That means your variable "gameTimer" is local to the function memory(). You won't be able to use your variable anywhere outside of this function because it exists only inside of memory(). To solve this issue, you have move it outside of the function:
private var gameTimer:Timer;
public function memory():void
{
levelDuration = 10;
gameTime = levelDuration;
gameTimer = new Timer(1000,levelDuration);
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired);
gameTimer.start();
}
That will solve all your issues.
Alright, so I am fairly new to AS3 and I have a level in my game where you have to stay alive for 45 seconds. If I use a code like (Or if there is a better code, I'll use that one)
var myTimer:Timer = new Timer(1000, 1); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runOnce);
myTimer.start();
function runOnce(event:TimerEvent):void {
trace("runOnce() called # " + getTimer() + " ms");
}
How can I use this to make my game move to scene 6 if they stay alive for 45 seconds? I also want to display text on the animation that keeps track of how long they've been alive so they know how long they have left. How could I accomplish this?
private var startTime:int;
function startGame() {
// this is called when your game starts
startTime=getTimer();
... // rest of init code
}
function onEnterFrame(e:Event):void {
// main loop, whatever you need to do in here
currentTime=getTimer()-startTime; // here we receive the elapsed time
// pause handling is excluded from this example!!11
if (weAreDead()) {
survivalTime= currentTime;// here
...
} else if (currentTime>45000) {
//advance to scene 6 here
}
}
Set the listener for Event.ENTER_FRAME to onEnterFrame, start the game with setting the stored time, and pwn.
The simplest solution is to go ahead and use the timer, but set the value to 45000 and make sure to keep a reference of the timer or it will be garbage collected. Also, create a separate function which allows you to kill the timer from anywhere if this particular thing ever needs to just "go away" without completing.
public static const DELAY:int = 45;
private var _timer:Timer;
public function setTimer():void
{
_timer = new Timer( DELAY * 1000, 1 );
_timer.addEventListener( TimerEvent.TIMER_COMPLETE, timerCompleteHandler );
_timer.start();
}
private function timerCompleteHandler( event:TimerEvent ):void
{
disposeTimer();
goDoTheThingThatYouNeededToDo();
}
public function disposeTimer():void
{
_timer.stop();
_timer.removeEventListener( TimerEvent.TIMER_COMPLETE, timerCompleteHandler );
_timer = null;
}
I am writing simple metronome component using Flex + AS3. I want it playing 'tick1' sound after, for example, each 500 millisecond and each 4th time plays another sound 'tick2'. But actually delay between sound is not equivalent - sometimes lesser, sometimes greater a bit. I testing it on latest Chrome.
Here my code:
//Somewhere here button bound to the 'toggle' function
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.media.SoundTransform;
import flash.media.SoundChannel;
private var bpm:Number = 120; //2 bit per second, delay=500ms
private var period:Number = 4;
private var timer:Timer = new Timer(bpm, period);
[Embed(source='sounds/1.mp3')]
private var tickSound1Class:Class;
private var tickSound1:Sound;
[Embed(source='sounds/2.mp3')]
private var tickSound2Class:Class;
private var tickSound2:Sound;
private var trans:SoundTransform = new SoundTransform(1);
private function init():void {
....
tickSound1 = new tickSound1Class() as Sound;
tickSound2 = new tickSound2Class() as Sound;
update();
timer.addEventListener(TimerEvent.TIMER, onTimerEvent);
....
}
private function update():void {
timer.delay = 1000 * 60/bpm;
timer.repeatCount = 0;
}
private function toggle():void {
if (timer.running) {
timer.reset();
startStopButton.label = "Start";
} else {
update();
timer.start();
startStopButton.label = "Stop";
}
}
private function onTimerEvent(event:TimerEvent):void {
var t:Timer = event.currentTarget as Timer;
if (t.currentCount % period == 0)
tickSound1.play(0, 0, trans);
else
tickSound2.play(0, 0, trans);
}
I think there are two main reasons:
It is known that Timer object in Flash Player is inaccurate, delay between it's fires fluctuates.
Sound.play() method also introduces some delay before the sound actually starts to play, and theoretically this delay can fluctuate. The delay is especially noticeable in PPAPI version of Flash Player being used in Chrome.
There are several solutions. I would suggest one of these:
Use pre-composed sound of the whole metronome cycle (tick1-pause1-tick2-pause2) and just loop it using the second argument of Sound.play() method;
use dynamic sound generation.
The second option is more flexible but is more difficult to implement. Basicaly, you'll need to create a new instance of Sound object, subscribe to it's SAMPLE_DATA event and call it's play() method. In the handler you'll check event.position / 44.1, which will give you current position of sound generation in ms. Then, if you decide that it's time to play tick1 or tick2 sound, you'll call tickN.extract(event.data, ...), where tickN is tick1 or tick2 Sound object, or write the silence otherwise.
You can read more about dynamic sound generation here.
Also, notice that when you call Sound.play() it returns a SoundChannel object, which has the position property. Is it a position in ms of a sound that is being played (not generated) at the moment, and it is accurate. So, using this property, you can come up with the third approach: create a Sound object and setup a SAMPLE_DATA handler like in the dynamic sound generation solution, but write the silence (zeros) to the event.data object inside the handler all the time. This is needed to obtain a sound channel without actually playing a sound. Then, use high frame rate (60 FPS) and a Timer with the smallest possible delay (1 ms). Each time the Timer fires, check soundChannel.position to determine whether it is time to play the tick sound, and, if it so, just play it like you're doing in your example. This approach is likely to solve the problem of the Timer inaccuracy, but it cannot deal with the delay caused by tickSound.play() method.