8bitrocket.com
9Feb/100

AS3 Tutorial: Controlling the Main Timeline of a SWF Embedded at Compile-Time

AS3 Tutorial: Controlling the Main Timeline of a SWF Embedded at Compile-Time

Today I was working a a new piece of the Essential Flash Games framework that allows sponsor swf files to be embedded at compile time and displayed before a game reaches the title screen. I am using Flash Develop and the Flex SDK, but the embed compiler directive is also available in the latest versions of the Flash IDE. I wanted to embed rather than load to ensure that the final swf file is a single self-contained unit that can be easily spread to game portals. I tried this a number of different ways to no avail. Most of the standard swf embed code works fine with assets inside the library of embedded swf, but not when trying to control the main time line of the swf itself. So, this is what we are going to cover: If you have been trying to embed swf files at compile time but cannot get your code to recognize the embedded swf, or the totalFrames attribute of the embedded swf returns 0, or if the swf only shows the final frame of your animation then read on. I had all of those problems today and more, but finally figured out a method to make this work properly.

Controlling the Main Time Line of a swf file embedded at run time.

1. Here is the asset that we are going to embed. I Embed all of my assets in a separate Library class as Static Const variables. This could just as easily be in the main document class for your game or application. I will do it the later way here to keep it uncomplicated. This assumes that the 8bitrocketlogo2.swf is in the same folder as the document class. This logo swf is a multi frame animation with 85 frames on the main time line (its just important that there is more than a single frame because you will want to see if you can play and jump to frames to ensure you have control over the time line).

[cc lang="javascript" width="550"]
[Embed(source = '8bitrocketlogo2.swf', mimeType="application/octet-stream")]
public static const LogoAnimation:Class;
[/cc]

This embeds the swf file as a BiteArrayAsset or a pure binary data stream. The mime-type of "application/octet-stream" is needed to embed as this data type.

2. Next we need to be sure to import the necessary classes

[cc lang="javascript" width="550"]
import flash.display.Loader;
import flash.display.MovieClip;
import mx.core.ByteArrayAsset;
import flash.events.Event;
[/cc]

3. We will need to create these class level variables

[cc lang="javascript" width="550"]
public var loader:Loader=new Loader;
public var logo:ByteArrayAsset;
public var clip:MovieClip;
[/cc]

4. Even though the swf file was embedded at compile time we need to use an asset Loader object to make use of it. First we must instantiate the LogoAnimation class we created that is effectively the equivalent of a "linkage name" in the IDE. We do this by assigning the logo variable to be a new instance of this embedded swf:

[cc lang="javascript" width="550"]
logo = new LogoAnimation();
[/cc]

5. We cannot access this data right away for a couple of reasons. First, the data inside this class is not yet an instance of MovieClip. It is still a ByteArray. Second, even though the asset swf has been embedded, we have no idea whether or not the code can access it yet. I found this out the hard way (hair pulling trial and error). I don't know the actual reason for this, but  I know a way to mitigate it. The best way (that I have found) to know when this embedded data is be ready to be used is to "load" it into an asset Loader class instance and check to see when it's INIT event has fired off. Fair enough. Add these lines to do just that:

[cc lang="javascript" width="550"]
loader.contentLoaderInfo.addEventListener(Event.INIT,loadCompleteListener,false,0,true);
loader.loadBytes(logo);
[/cc]

The contentLoaderInfo attribute of the Loader class will fire off the Event.INIT event when the Loader.content is ready to be used. Also notice that we have also called the loader.loadBytes method and passed in the instance of our embedded LogoAnimation class swf (the logo variable).

To be sure that the swf is completely ready before we try to access it, we will create the loadCompleteListener function to catch the INIT event.

[cc lang="javascript" width="550"]
private function loadCompleteListener(e:Event):void {
 
clip = MovieClip(loader.content);
addChild(clip);
clip.stop();
}
[/cc]

The clip variable in a MovieClip instance that we set to be the content of a MovieClip cast of the loader.content attribute. The loader.content contains the actual binary data of embedded swf but AS3 has no idea what to do with it. We cast it as a MovieClip and assign it to our clip variable so we can use this reference throughout our code without having to re-cast every time. The clip variable can now be used to control an instance of the embedded swf just like any other MovieClip instance.

When a swf is embedded all of the time line code is ignored. We need to call the clip.stop() function to make sure the clip stays on frame 1 until we want to actually play it. We also called the addChild(clip) function here, but it does not need to be called until you want to display the clip on the screen.

That's it. It was pretty simple after I finally got the hang of what was going on.

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.

This site is protected by Comment SPAM Wiper.