I have the following code which should add a MovieClip and add a frame script to the MovieClip to be executed once the clip has finished playing. The code shown below however triggers the frame script as soon as the MovieClip is added and I can't figure out why.
function debugClick(e:MouseEvent) : void
{
nextLevAnim = new NextLevelAnim();
gfx.addChild(nextLevAnim);
nextLevAnim.addFrameScript(nextLevAnim.totalFrames, NextLevel);
}
function NextLevel() : void
{
nextLevAnim.addFrameScript(nextLevAnim.totalFrames, null);
// Actions....
}
I've tried with simpler examples and it works fine, the MovieClip is 21 frames long and I've tried triggering the frame script by totalFrames and totalFrames - 1, running out of ideas!
hmm, I haven't worked with addFrameScript much so I can't tell what is causing the problems, but you could try using a hack.
use an onEnterFrame listener and check if the current frame equals the number of frames (-1).
it's not ideal, but if you're stuck on this it might just do.
as far as addFrameScript goes, my guess is that it's not working because addMovieClip doesn't take effect until the render part of cycle, so the totalframes are still 0 for the child added. You can add a listener for onAddedToStage or onAdded and add the addFrameScript event handler after the MovieClip gets initialized
What is totalFrames variable in this case? Have you tried to trace() it? I'm pretty sure it does not contain the proper value of the total number of frames in nextLevAnim and you should probably use nextLevAnim.totalFrames instead.
Related
I would like to know how to create in Adobe Flash CS3 a button that will execute a function (like gotoAndPlay(51) but ONLY when playhead hit a defined keyframe from timeline.
Here is a drawing that does explain better what I want to do
So after I click the button, it will wait until the playhead hit the closest defined keyframe, only then it will execute my desired function.
Any help is appreciated.
There are a few ways to accomplish this. The most succinct way is to use an undocumented* feature called addFrameScript
What you can do with that method, is place code on a specific frame at runtime.
So, you could do something like:
//listen for the click on your button
myButton.addEventListener(MouseEvent.CLICK, buttonClickHandler);
//which frame should the gotoAndPlay run on?
var targetFrame:int = 19; //this is actually frame 20, since frames are 0 based in script
//this function will run on the above frame
function goto51(){
//goto frame 51
gotoAndPlay(51);
//remove the frame script
addFrameScript(targetFrame, null);
}
function btnClickHandler(e:Event) {
//use addFrameSCript to run the function goto51 on the target frame
addFrameScript(targetFrame, goto51);
}
*-one should point out that using undocumented features of a language comes with risk of the feature being taken out on a future version, however given the current life cycle stage of AS3, this is very unlikely
This is an if stament on a frame on the root. I want to loop Carrera(a lenghthy movieclip) from frame 2 back to frame 1. (For testing purposes)
This is the code:
if (MovieClip(root).Carrera.currentFrame==2){
MovieClip(root).Carrera.gotoAndPlay(1);
}
The MovieClip keeps going, ignoring the if statement.
What I'm doing working?
There's no bug with the if statement, it's just not being evaluated when you expect it to be.
When you place code in a frame, it gets executed right away, when that frame gets entered. So, when the first frame starts, the if is executed, whose condition is false at that time. And it never gets re-executed, because you never tell it to be. There is no such thing as "standing orders" in AS3 ;-)
Instead, you can check on every frame by adding an event listener:
addEventListener(Event.ENTER_FRAME, function (e) {
if (MovieClip(root).Carrera.currentFrame==2){
MovieClip(root).Carrera.gotoAndPlay(1);
}
});
Or, you can just place gotoAndPlay(1); on the second frame of Carrera (not the root).
You have to understand that you are running this if statement only once. Even if the Carrera clip is at frame 2 in that exact moment, the clip will jump to play 1 and continue playing - there is nothing to make it do the jump again, and thus there can never be a loop.
In order for this to work, you have to run this same statement again and again - every time the clip jumps to a new frame.
For example, you can do this by a) attaching this script to frame 2 of the Carrera clip (not the root!):
gotoAndPlay(1);
or b) adding an event listener to it:
MovieClip(root).Carrera.addEventListener (Event.ENTER_FRAME,
function ( ev:Event ) : void {
var cl:MovieClip = ev.target as MovieClip;
if (cl.currentFrame == 2) cl.gotoAndPlay(1);
}
There are many more ways to do this, but unless you are going to do more complicated things than jumping to frames every now and then, I would advise you to go for the first option - it seems you should learn more about ActionScript before trying out event listeners.
Things to test...
Is MoveClip(root) defined at the point in execution?
Is MoveClip(root).Carrera defined at the point in execution?
Is MovieClip(root).Carrera playing (or have you called stop on it so it's just sittin in frame 1?
I have a function that states when movieclip1 is dragged and hits a line then it stops the drag, however it seems to stop the entire drag function in the swf on the other movieclips even though they arent called in the function. Can somebody please help me with this.
Regards
T
Here is the code:
function hitTest(event:Event):void
{
if (movieclip1.hitTestObject(line))
{
movieclip1.stopDrag();
}
else
{
}
}
Are you absolutely positive you only have one instance of movieclip1 on your stage? Definitely double check. Are you creating them dynamically, or are they preloaded when your SWF loads?
If they're preloaded:
Perhaps during testing you made some quick copies of it, and now those copies have the same name and they're all responding the same. That's my first guess.
If they're loaded dynamically:
Check the function where they're being created. If you're naming them in a loop (with a number on the end like the above), be sure that you're properly increasing the numeric value used on the end.
I want my movieclip to play once and stop on the last frame. I use the following code in the loop of my movieclip class. (this is as3)
if(currentFrame == 120)
stop();
120 is the last frame. It plays once. but the problem is it goes back to frame 1 again. is there a better method of stopping a movieclip on a particular frame.
If you want to do it with actionscript and not add a stop() to the last frame on the timeline manually, then you can use the undocumented addFrameScript() method.
mc.addFrameScript(mc.totalFrames - 1, function():void
{
mc.stop();
});
Can't remember the scope of the function, but you can either use mc.stop(), or just stop().
*EDIT - Added -1 to the first parameter of addFrameScript, because it is zero based (so to put a frameScript on frame 10 you would put 9).
On the timeline, you can just put a keyframe at the end, and add the stop(); method there. When it reaches that frame, the stop(); method will execute, and the clip will stop.
Assuming you are using the timeline that is, but sounds like you are.
Easiest way:
Just select the last Frame in the timeline. Open the Actions pane(F8). Ensure the frame u selected is still selected, if not then select again while the Actions pane is open.
After selecting, just add the simple stop() function in the the 'Action-Frame' pane.
//add the following line to the actions pane of the last frame.
stop();
You're done. You can optionally add a replay button if needed.
This seems more along the lines of what you're looking for:
addEventListener(Event.ENTER_FRAME, function(e:Event){
if(currentFrame == totalFrames){
stop();
removeEventListener(event.type, arguments.callee);
}
});
I added an event listener (for Actionscript 3) so on every frame this function will fire and check what frame it is on. If it's the last frame it will stop. Based on your example I'm presuming you have a class that's extending MovieClip.
I've got an AS3 project that I'm building in FlexBuilder.
In my main class's constructor, I've got this:
stage.addEventListener(Event.ENTER_FRAME, stage_enterFrameHandler);
And then the event handler function:
private var tempCounter:uint = 0;
private function stage_enterFrameHandler(event:Event):void
{
stage.removeEventListener(Event.ENTER_FRAME, stage_enterFrameHandler);
tempCounter += 1;
trace(tempCounter);
}
When I run in debug mode, tempCounter writes out once, as 1. Why is this? I though the whole point of Event.ENTER_FRAME is that it keeps firing.
The documentation says:
If the playhead is not moving, or if there is only one frame, this event is dispatched continuously in conjunction with the frame rate. This event is dispatched simultaneously to all display objects listening for this event.
So why would I not see that counter incrementing about 30x a second (which is what I have the frame rate set to)?
EDIT NOTE:
OK, well, doh, I've figured it out. It's because I immediately remove the eventlistener. The ENTER_FRAME event does keep firing... The only reason the code is done this way (code I inherited) is, I suppose, that CREATION_COMPLETE isn't available if you aren't using the flex framework.
The answer is simple as soon as enter in your enter frame you are removing the listener so the next time the enter frame event occured there is no one to react to it.
remove the line
stage.removeEventListener(Event.ENTER_FRAME, stage_enterFrameHandler);