How to Switch to a Frame Visually, Without Running its Actionscript? - actionscript-3

I've run to a problem. I've got a SWF that is divided into frames.
What I'm trying to do, is switch to one of my frames which has actionscript code, but I just want the visual elements to be displayed, without executing the actionscript code it contains.
I am trying to switch to this frame using gotoAndStop("frame-name");
I've tried to add a boolean value to the code in this frame, that decides whether or not it gets executed, I set the value the first time that frame's actionscript is executed, but this value is ignored as if using gotoAndStop
creates a new instance of that frame's actionscript code, so it doesn't retain the boolean value I set.
Is there any way to not allow actionscript execution of this frame?

Nope, not really, at least not given how the solution 'seems' to work!
What you can do is to create another keyframe (f6 in editor I think) that looks identical and then do gotoAndStop("other_frame").
As long as that keyframe doesn't have any code you're good to go :)
The most common solution for flash-development is to not have code inside your fla-file and instead have it in AS-files and only have visual elements inside the fla. That way you have full control of what is happening and when etc...

Related

as3 how can i prevent that a new instance is created by entering a frame?

i am working with several nested movieclip objects in a project. but i get into trouble with the buttons i created and implemented in the nested movieclips:
to describe it in a simple way:
I have a main movieclip with five frames, including two buttons with listeners to browse between the frames. Then inside of one Frame I have another movieclip with its own buttons. i instanciated it by hand not through code and gave it a specific name like "nestedMc".
Now I dont want to build the Listeners for those buttons inside the class of the nested movieclip class but in its parent class, which works fine until i then goto another frame in the main movieclips timeline and come back.
obviously every time flash enters a frame its contents get created anew (and therefore get new instance names). I could now try solve this through filling the frames via code.
But maybe there is another way to make sure the frame contains the same instance everytime i enter?
Timeline scripting is a dirty business, and really, a carry-over compatibility layer for Actionscript 2 projects. Whenever possible, I highly recommend not doing it, and simply keeping all of your code in your document class. As you're experiencing, timeline code causes headaches.
Consider instead just creating both states of your Stage (it sounds like that's what your two buttons are jumping between) and simply hiding them offstage or setting their alpha to zero and their mouseEnabled state to false. Furthermore, if the purpose of your frames is to play animation (a tween), consider instead switching to a much more powerful suite such as TweenLite. Moving an object over a hundred pixels (smoothly) can be as easy as:
TweenLite.to(redBall, 3, {x:100});
Now, if you're manually adding these items to the stage, as long as the object is a dynamic one, you can assign an instance name to it which will be saved between frame loads. Be aware the object name is not the same as the instanced name. For example:
var redBall:Ball = new Ball();
redBall.name = "bubbles";
The object's name is Ball, but it's represented as a variable called redBall. Its actual DisplayList name will likely be ambiguous (such as "Instance71"), and I can manually define it as "bubbles". 3 different names for the same object, all very different and necessary.
Even if you give the object a displayList name, you may not be able to reference it through code unless you enable Automatically declare stage instances, which basically creates on each object a pointer to the displayList object.
That said, you can always fetch the object by other means. Obviously, your buttons are always appearing, but you're trying to find a very specific object on the stage. At this point, we can use getChildByName() or getChildAt().
Hope that helps.
-Cheers

How can I send control of the playhead back to a parent timeline from a movieclip using createJS?

I'm making a multi-part introductory animation for a game. It works when I preview in Flash, but not when I export using the CreateJS toolkit to get HTML5 output.
On my scene's timeline, I have this.stop(); on the first frame, as well as a movie clip that contains several seconds of animation (and which may have to change in length as we develop).
My second frame is labeled "sc2" and I would like the animation to pick up there when the first movieclip is finished. To accomplish this, I went into the first movie clip and put this on the last frame:
_parent.gotoAndPlay("sc2");
This works fine in Flash, but perhaps I can't use the _parent object in JS? Is there an alternative way to access the flow of control or another way to accomplish this? My goal is to avoid doing animation on the main timeline and to control the flow by scripting there so that if the length of the individual sections of animation changes, I don't have to change the start and end frames of the various sections in several places.

Internal AS3 preloader & stage issues

I need to create a single SWF with no external files, so I'm trying to add an internal preloader to my Flash project which has [embed] assets. I know [embed] causes problems with preloaders because it puts the assets on frame 1. I have tried the solutions recommended in these posts, where you set the document class to your preloader class:
Preloader for SWF with embed bytearray
How to create Preloader in AS3
I can get it to work, but ONLY if I comment out any lines of code that involve the stage, otherwise I get an "Error #1009: Cannot access a property or method of a null object reference." Those lines are essential though, so does anyone know how to fix those errors with the stage?
You haven't posted your code or your fla, so all I can do is share what works for me.
First, I wouldn't use Embed. Instead, use a swc. I have found that Embed can be unreliable as far as actually getting the entire asset in there (at least when publishing with Flash Builder + Flash Pro, which is my workflow).
Once you have your assets in a swc, try the following steps:
Set your export frame to Frame 10 (or any frame other than 1--I like frame 10 because then you can read the label that says "Preloader")
Put your actual content on frame 11. You can structure this a lot of ways. Since I program to Interfaces, I give whatever is on frame 11 an instance name and then use a setter to determine that my "first thing" has been placed on stage. I can get away with this because my main Document Class just knows the definition of the Interface, not the full implementation of the Class, so the Class does not need to load for the main Document Class to work. You probably aren't truly using the timeline and probably didn't program to interfaces, so you'll probably just set the base class of the symbol that's on frame 11 to the main logic of whatever you're trying to do.
Put your preloader graphics in Frame 1. I'm not sure why your stage references are so important. I, personally, don't use any logic in the preloader. Instead, I use a spinner that spans frames 1-10 (plus the word "Loading...". The spinner just spins while the classes load. The embed frame acts as a temporary "stop" that just holds the timeline back until those classes have been loaded. Once the classes have been loaded, the timeline will act like you called play() on it. So it really can be that simple. If you need it to be more complicated, give one of your preloader graphics an instance name and set up a getter/setter pair for it, then use the setter to trigger your logic that accesses the stage. You are pretty much guaranteed to have a valid stage at that point.
Word of warning: if you did make use of the timelime, you will get strange results if you try to jump to a frame that isn't loaded yet, so make sure to check to see if a given frame is loaded if it's near the end of your main timeline and your main timeline is heavy with assets before calling goToAndPlay() or goToAndStop().
Some references that might help you further:
Preloaders vs as 3 (I'd recommend you read the entire series this is part of. This is an amazing series I wish I'd found 3 years ago)
Solving the Frame 2 Problem Presentation and code
Combining the Timeline with OOP The example code for that is here (long story)

Why would a keyframe in Flash fail to update an object's position as defined in the keyframe when the play head is sent to that frame?

I have a background MovieClip in a custom button class, which moves the play head to a different frame (via gotoAndStop("framename")) depending on which mouse events it receives.
When the mouse up event is received, it sends the play head back to the "release" frame, where the background should shift back to its original location, but instead nothing happens and the background remains where it was. It's as though Flash is not honoring the background's position defined by the key frame it enters.
The only workaround is to add a frame script to each frame which manually sets the x and y position to what it should be, but this defeats the purpose of using keyframes for the position.
What is going on?
Try calling event.updateAfterEvent(), it's supposed to
Instructs Flash Player or Adobe AIR to render after processing of this event completes, if the display list has been modified.
from here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/MouseEvent.html#updateAfterEvent%28%29
This appears to have been a bug in the Flash IDE, specifically some kind of corruption in a timeline layer.
The corruption originated in Flash CS4, but persisted when opened and compiled in Flash CS5, which is why I suspect it was some kind of content-generation bug, rather than something specific to either IDE version. The IDE probably gets confused when you construct the timeline out of order or drag things around, rename things, copy things in from other files, etc. I think, specifically... it was the fact that I copied this particular object in from another file. And it wasn't even a complex object, it was just a MovieClip that contained a rounded rectangle and had a drop shadow applied, seriously.
Steps I took to resolve the issue were to remove any classes associated with the library item, reverting it back to a standard MovieClip. I then completely removed the problematic layer. I then reassigned the class to the library object and exported it for ActionScript. Finally, I rebuilt the layer from the first frame, adding subsequent keyframes as necessary. I reapplied filters, and adjusted the clips location on each frame.
Now, everything is functioning as expected. The clip's position, filters, etc. are all updated as expected when the playhead moves to any frame. It's working now as expected, so I wasn't doing anything wrong or not possible. It simply must have been some kind of incrementally constructed key framing confusion within the data structures of the IDE. Glad it's working now.

symbols placed on the timeline become undefined if stepping backwards

I am using the frames in the timeline of a .swf as pages in a flash app. The user can advance to the next page by clicking a button that takes her to the next frame. Similarly, it is possible to navigate to the previous frame/page as well.
Most of the content is placed on the stage (i.e. created by dragging an instance of a library symbol to the stage) but properties of those instances, such as .visible might be changed via actionscript. Also, some objects are loaded from external flash files and displayed programmatically with addChild / addChildAt.
The problem is, if I am on Frame N+1 and there is an object displayed on the stage programmatically (i.e. with addChild, not by having it placed on the stage) and navigate to Frame N where there is an object that is placed on the stage (i.e. dragged from the library),
then the instance of that object is undefined/null and throws an error if I try to set its properties (like .visible).
The error does not occur if I am moving to the NEXT frame, only if I am moving to the PREVIOUS one. Therefore I assume that some kind of initialization is not getting called while going one frame back.
I was also thinking that the objects would just not "live" to the next timeframe, that is, their value would be lost and re-initialized because of scope, but if there is no dynamically created object on the stage, I can navigate back and forth just fine.
Is there a way to ensure that the objects created on the stage do not disappear while navigating back to the previous frame?
The first, and more useful, part of the answer is this: timeline keyframes and scripts can give conflicting information about display objects - whether they should exist, where they should be, and so on. For example, when you add an item by playing into its frame, and then delete it with script, and then play into its frame again. When this happens, there's no unambiguously correct thing for Flash to do, so it tends to be unpredictable. I believe what generally happens is that once you fiddle with a given object via script, it's considered to no longer pay attention to the timeline - but your mileage will vary.
Having said that, the reason things are different when you play backwards is the second and more arcane part of the answer. Internally Flash functions differently when seeking forward and backwards on the timeline. Flash internally treats keyframes as changes to be applied in the forward direction, so as you play forward, it applies those changes in sequence. When you move backwards, however, from frame N+X to frame N, it doesn't scan through the intervening X frames reversing those changes - it jumps back to frame 1 and fast-forwards along to frame N. Normally, it amounts to the same thing and you don't need to worry about it, but when you get into the twitchy area where scripts and the timeline have a different idea of what should be on the stage, you're liable to see things behave differently depending on which way you jump (as you are now).
The super-short version is, for things to work predictably, try to ensure that any given object gets added, updated, and removed the same way - either all via script, or all via the timeline. When that seems impossible, fiddle with your content structure - usually, the best solution is to change your object into two nested ones, so that the things you want to do with script occur one level higher or lower than the things you want to do with the timeline.
I'm not sure I got your question right, but as3 does not instantiate elements on the timeline as soon as you gotoAndSomething, but later that frame.
That is, you can't
this.gotoAndPlay(10)
this.elementOnTimelineFrame10.DoSomething()
without errors.
I remember using this chunk of code in the past to work around this problem. It uses the Stage.Invalidate() function to wait for an Event.RENDER before trying to access and children, more info (although vague as hell) is here
private function init():void
{
stage.addEventListener(Event.RENDER, stage_renderHandler);
}
private function stage_renderHandler(evt:Event):void
{
// Run your code here
updateChildren();
}
private function enterFrameHandler(evt:Event):void
{
// triggers the RENDER event
stage.invalidate();
}
This also might me very costly (performance wise). I would strongly advise against dynamically adding/removing objects to an existing timeline, is there any way in which you can place an empty Sprite above the timeline animation and use that for all your dynamic content?
Hope this helps