AS3: MovieClips play as soon as they are instantiated? - actionscript-3

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();

Related

Actionscript 3 - Does handling an event work separately than a function

Let's suppose I have some event handlers set, and then I have this loop which is working, if I fire the event, will the function be triggered or will it get stuck?
Flash is, for the most part, single threaded. This means that it can only do one thing at once. (You can use Workers nowadays to get around that, but we'll ignore those for the sake of this answer)
So, events can only fire when there is a gap in execution. If you have a loop running, there won't be such a gap until after that loop, and any additional code, has run.
The answer to your question is it will not run until the loop has finished. And any events that are triggered during code execution are queued and fired in order as soon as a gap in execution occurs.
If you are dispatching events within your loop then your application will respond to them.
If you have a loop that is doing it's own thing and your code that dispatches events is outside of that then your application will not get those events while the loop is occurring.
In the following examples, events will be dispatched:
for (var i:int;i<1000;i++) {
// do something
dispatchEvent(myEvent);
}
...events will not be dispatched:
for (var i:int;i<1000;i++) {
// do something
// no events dispatched while in this loop
}
dispatchEvent(myEvent);
If you are in the for loop too long, AIR or the Flash Player runtime will timeout.
Possibly a better approach would be to use a ActionScript worker as the other poster posted or check the time you've been in the loop and break out of it after a specific amount of time. You would then be breaking your work up into chunks.
var landBeforeTime = getTimer();
for (var i:int;i<1000;i++) {
// do something
// check we aren't taking too long
if (getTimer()-landBeforeTime>1000){
notDone = true;
break;
}
}
if (notDone) {
// come back in the next frame and finish this loop
setTimeout (myForLoop, 100);
}
The previous code is an example. You'll want to use enterFrame and tidy things up.

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

Exit Event when move to other frame in AS3

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.

Flash AS3 game loop : functions on separate frames

I want to use this to keep my functions on the current frame
function gameloop(e:Event) {
if(currentFrame > 1){
return;
}
}
But I also need to have functions in the game loop separate from frame 1, I just can't do that or else I get the error
duplicate function definition
I need help, and any is appreciated
It sounds like you aren't using OOP, and that is alright. Your problem is that you're remaking functions in subsequent keyframes. If you want to avoid using classes in AS3, the best way is to have a central layer with a single keyframe that spans the entirety of your movie. You put all your global variables and function on there. Then you can access them throughout the entire movie. You are getting a 'duplicate function definition' error because you are rewriting a function rather than extending its scope within the timeline.

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.