Exit Event when move to other frame in AS3 - actionscript-3

I trying to get an event when move from one frame to another in AS3.
I have tried with the EXIT_FRAME it always calling.
I need to get state when move from one frame to another.
addEventListener(Event.EXIT_FRAME,exitfunc);
function exitfunc(e:Event):void{
trace("EXIT_FRAME");
}

as Nagarajan sugges, you can dynamically add a script to a frame.
For example in your main class
package {
import flash.display.MovieClip;
public class Test extends MovieClip
{
public function Test()
{
this.addFrameScript(4,frameFunction); // (add script to frame 5, zero based)
}
private function frameFunction():void {
trace ('Do something when play head enters frame 4')
}
}
}

because their names are misleading. Event.EXIT_FRAME doesn't execute once when the playhead exits a frame. it executes repeatedly.
likewise, Event.ENTER_FRAME doesn't execute once when the playhead enters a frame. it executes repeatedly.
you can execute a function when the playhead enters a a frame by adding a function call to the frame:
f(); // attached to a frame will call the function f when the playhead enters this frame. and there are other ways to do this.
you can execute a function when a playhead exists a frame by invalidating the stage and using a render event when a goto is executed:
stage.invaidate();
this.addEventListener(Event.RENDER,ExitingF);
this.gotoAndPlay('whatever');
function exitingF(e:Event):void{
// this code executes when this frame is exited and 'whatever' is rendered
(=displayed);
}

There's only one good way but that might be beyond your skill level. Create a class that extends MovieClip and override the gotoAndStop and gotoAndPlay methods then simply make them dispatch a custom event (don't forget the call to super). That custom event can carry the frame label, index, etc ... You'll have to make sure your MovieClips/Document class implement that class and everything will be done automatically.
This will allow you to keep track of when you leave a frame and move to another with a call to gotoAndStop or gotoAndPlay. If you only want to keep track of normal playhead move then the ENTER_FRAME event is enough.

Related

AS3 - reset delay on Timer

I have a private Timer object in an AS3 Class called _countDownTimer.
When the class is instantiated, I also initialize the Timer once like so with some arbitrary delay
_countDownTimer =new Timer(10000, 1);
_countDownTimer.addEventListener(TimerEvent.TIMER, onCue,false,0,true);
The problem is I need to change the delay time every time the Timer runs.
So in another method I first redefine a private var _newDelayTime and then call startMyTimer() to redefine the delay and start the _countDownTimer.
My question is, should this work properly?
Do I ALSO need to instantiate a NEW _countDownTimer and re-add the listener every time I change the delay?
private function startMyTimer():void{
_countDownTimer.reset();
_countDownTimer.stop();
_countDownTimer.delay=_newDelayTime;
_countDownTimer.start();
}
private function onCue(e:TimerEvent):void{
trace('do stuff');
}
You do not need (or want) to create a whole new timer object.
Setting the delay while the timer is running is perfectly acceptable.
Do note though, that setting the delay resets the timer, as per the documentation:
If you set the delay interval while the timer is running, the timer will restart at the same repeatCount iteration.
So, if the timer doesn't actually need to stop, take off the 1 repeat count when you instantiate (and start it), and then just change the delay whenever you need to.
_countDownTimer.delay=_newDelayTime; //no need to reset/stop/restart
as I know, as3 Timer class is not precise in counting time... it depends on how fast listener function executes (waits until function finishes its job and continues counting). I prefer using greensock... but if it's not so important for you to have precise time than you can do something like this:
private function onCue(e:TimerEvent):void
{
trace(e.currentTarget.delay);
_newDelayTime = Math.round(Math.random() * 999) + 1;
startMyTimer();
trace('do stuff');
}
you can manipulate with _newDelayTime diffenetly... this should work properly and you wont need to re-add listeners

Awkwardness Between Scenes (What happened to my symbol?)

Say we have a flash file, and all the code and objects on the file are described below:
Scene One:
only one symbol with the instance name "char" is on the stage
Code for Scene One:
import flash.events.Event;
stage.addEventListener(Event.ENTER_FRAME,update);
function update(e:Event){
trace(char);
}
play();
Scene Two:
only one symbol with the instance name "char" is on the stage
Code for Scene Two:
stop();
If you try this out yourself, you will find that the Flash traces the object char to be "null" for a split moment, and then traces it properly once it has discovered the symbol on the second scene. Does anyone know why this is, since there is a symbol with the instance name "char" on both consecutive scenes?
I could not find any specific documentation related to this other than that which is provided by Adobe for the Event class, but I believe what you are experiencing is related to the differences between the events Event.ENTER_FRAME and Event.EXIT_FRAME and how the Flash runtime initlializes objects for use.
I ran a test using your code with Event.ENTER_FRAME, and experienced the same results you encountered; however, when I used the Event.EXIT_FRAME event, the display object did NOT trace as null at all.
Then I took it a step further and set up my timeline exactly as yours; however, changed the event code in Scene 1, Frame 1 to be:
import flash.events.Event;
import flash.display.MovieClip;
stage.addEventListener(Event.ENTER_FRAME,update);
stage.addEventListener(Event.EXIT_FRAME,update);
function update(e:Event){
if( e.type == Event.ENTER_FRAME ) {
trace("ENTER FRAME: " + currentScene.name);
}
else if( e.type == Event.EXIT_FRAME ) {
trace("EXIT FRAME: " + currentScene.name);
}
trace(char);
}
play();
And when executed noticed something interesting:
EXIT FRAME: Scene 1
[object MovieClip]
ENTER FRAME: Scene 2
null
EXIT FRAME: Scene 2
[object MovieClip]
ENTER FRAME: Scene 2
[object MovieClip]
EXIT FRAME: Scene 2
[object MovieClip]
...
The Event.ENTER_FRAME event was never called on Scene 1. Probably because that event had already occurred prior to the code on Scene 1, Frame 1 being executed.
The null reference was actually in relation to the char instance not yet initialized on Scene 2. Once the playhead was exiting the frame, probably when the instance was able to be referenced, it read as a MovieClip.
These behaviors are [probably] the reason why so many people recommend using a document class to add objects to the stage as necessary, attaching listeners to the Event.ADDED_TO_STAGE to know when they were added, so that you can handle functionality at the proper point in time that they are actually added to the stage; instead of waiting for the object to be able to be referenced via the timeline. My best guess is that if the ENTER_FRAME event had fired on Scene 1, it too probably would have traced null for char, just like it traced null on Scene 2. It may be null because the display object on the stage isn't yet initialized and so the code reference to that object isn't yet initialized either.
I wish I had more time to afford to investigating this for you, but this is the best test and explanation I could come up with to describe the behavior you are experiencing.
Cheers!

AS3: MovieClips play as soon as they are instantiated?

I made a short MovieClip that only lasts a few frames and put a trace statement on frame 1. Much to my surprise, simply instantiating it without even adding it to the stage made that trace statement start firing off immediately.
var m:MovieClip = new MovieClip(); //Trace statement begins going off repeatedly
Does that mean MovieClips automatically begin playing and looping as soon as they are instantiated? If so, should you always call stop() right after instantiating if you're not going to display it exactly at that moment? Unless your MovieClip only has 1 frame.
Yes, MovieClips begin playing auto-magically.
If you want to prevent this, you would need to stop it:
var m:MovieClip = new SomeMovieClip();
m.stop();

Do I have to set a removeEventListener when I called addEventListener?

I'm a beginner of ActionScript 3. Recently I'm trying to use addEventListener to invoke function. I found that there are some examples add a removeEventListener when they invoke functions, such as:
public function Away3DMultiMarkerDemo()
{
addEventListener(Event.INIT, initIN2AR);
super();
}
private function initIN2AR(e:Event = null):void
{
removeEventListener(Event.INIT, initIN2AR);
in2arLib.init( workW, workH, maxPoints, maxReferences, 100, stage );
in2arLib.setupIndexing(12, 10, true);
in2arLib.setUseLSHDictionary(true);
in2arLib.addReferenceObject( ByteArray( new DefinitionaData0 ) );
in2arLib.addReferenceObject( ByteArray( new DefinitionaData1 ) );
in2arLib.setMaxReferencesPerFrame(2);
in2arLib.setMatchThreshold(40);
intrinsic = in2arLib.getIntrinsicParams();
initCamera();
initAway3D();
initText();
initListeners();
}
My question is that do I need to set a removeEventListener each time when I called addEventListener? I did some research that the purpose of adding the removeEventListener is to release memory, otherwise program will keep listen events.
It is good practice to remove your listeners when you no longer need them. But that is a call you must make in each situation.
Adding an event listener by default will hang onto a reference of the thing it is added to. So if you add a listener to a movieclip, and delete that movieclip, it will not be garbage collected because the event listener still has a reference to it. For this reason it is good to remove any listeners on an object as part of your deletion process. Of course you can also use the "weak reference" argument in the addEventListener method, so the listener will not keep the garbage collector from destroying the object.
In the case of the Event.INIT event in your example; That should only ever fire once, so the event handler is the perfect place to make sure you remove the listener.
No. You only have to do this if you want the event to execute only once. You also call it when you no longer need the listener, so that it doesn't waste memory.
If you call it as the very first statement in the function that is called when the event is fired, it will ensure that the listener is only called once.

Does addEventListener (and removeEventListener) stack?

Given the below:
object.addEventListen(eventType01,handler01);
object.addEventListen(eventType01,handler01);
object.removeEventListener(eventType01,handler01);
How many event listeners for eventType01 are on object? One or zero?
Zero. If you call addEventListener, using the exact same arguments more than once all subsequent calls after the first "silently fail." Call add as many times as you want, but that single remove will wipe the listener away.
EDIT: Another thing to keep in mind is that there's no penalty to calling multiple identical removeEventListener() functions on the same object, aside from needless performance overhead. No deadly error will occur, it will simply "silently fail" much the same way as repeated identical addEventListener calls will.
EDIT 2: To answer #ThomasM :: if your listener "fires twice" then you do not have exactly the same listener. Try putting this quick and dirty code on frame 1 in a fla that has one square movieclip as a child:
import flash.events.*
function foo(e):void{
trace("hi");
}
this.addEventListener(MouseEvent.CLICK,foo);
this.addEventListener(MouseEvent.CLICK,foo);
this.addEventListener(MouseEvent.CLICK,foo);
Notice that your output when you click the movieclip is precisely one trace action.
Now add this line to the end of the code
this.removeEventListener(MouseEvent.CLICK,foo);
Even though you added foo as a listener for click 3 times, this one call kills the listener completely.
So if you're experiencing an issue where "the same listener" fire twice then probably what you're doing is something like this:
this.addEventListener(MouseEvent.CLICK, function(e){
trace("hi");
});
this.addEventListener(MouseEvent.CLICK, function(e){
trace("hi");
});
That will definitely "fire twice" because the listener functions ARE NOT THE SAME. They perform the same actions but they do not reference identical positions in memory. They do not point to the same function object. Furthermore this is highly bad practice because you have no way to actually remove those listeners. How would you do it? You have no reference to them.