Question

I'm trying to preload an swf which has an embed swf source. But it doesn't want to work. I tried the simple preloading, but the progress event only run after loading. Any idea?

public class MainShell extends MovieClip 
    {       
        [Embed(source = "Main.swf")]
        public var cs:Class;
        public var hsf8z42fdfd_as32:MovieClip;
        public function MainShell()
        {
            addEventListener(Event.ADDED_TO_STAGE, initialize, false, 0, true);
        }
        private function initialize(e:Event) {
            loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, error, false, 0, true);
            loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress, false, 0, true);
            loaderInfo.addEventListener(Event.COMPLETE, loaded, false, 0, true);
        }
        private function progress(e:ProgressEvent) {
            var done:Number = stage.loaderInfo.bytesLoaded;
            var total:Number = stage.loaderInfo.bytesTotal;
            var w:int = done / total * 100;
            loading.TT.text = String(w);
        }
        private function loaded(e:Event) {
            loading.parent.removeChild(loading);
            hsf8z42fdfd_as32 = new cs();
            hsf8z42fdfd_as32.addEventListener(Event.COMPLETE, onComplete);
        }
        private function error(e:IOErrorEvent):void{
            trace("Error!");
        }
        public function onComplete(e:Event) {
            addChild(hsf8z42fdfd_as32);
        }


It seems that the progress function only runs once after the file actually loaded. The progress event should run while loading, then why it doesn't?

Was it helpful?

Solution

You cannot pre load embed object. The concept of embed object is they are shipped with the container.

This is as if your MainShell contains the Main.swf.

That means that as soon as the class containing the embed object will be loaded (in memory) by the classloader you'll have at the same time all its dependencies (including embed objects). And only after that the code inside is executed, that is why you can't see the progress of the loading.

The content loader is for loading remote content from a server. With this you'll see the progress of the HTTP GET request (if it is not yet in the browser cache).

If you want to display the loading progress bar and so on you must not use embed content.

HIH

M.

OTHER TIPS

I've returned here to share my solution to this problem.

This is actually possible. However, the solution will not work so easily if your project uses library assets or timeline code. The solution requires your project to exist primarily is AS3 classes, so you may have to adapt your code in order for this to work.

First off, you'll need to download the Flex SDK (http://www.adobe.com/devnet/flex/flex-sdk-download.html). You will use this to compile your as3 classes into a .swf (Flex isn't going to mess with your project, don't worry). We'll come back to this after the initial setup.

Now, we are going to use an undocumented trick with the Flex SDK: the Frame metadata tag. The blog at http://www.bit-101.com/blog/?p=946 goes into more detail, but the Frame tag basically allows you to embed classes without calling upon them until a later time, not acting upon any of the code/embeds. We're going to stick this after the package definition, but before the class definition of our Main class, like so:

package {
    import flash.net.utils.ByteArray;
    import flash.display.Sprite;

    [SWF(width="720", height="480", frameRate="30", backgroundColor="#000000")] //we need this definition when compiling with mxmlc

    [Frame(factoryClass="com.aierou.game.Preloader")] //the factory class takes priority, so we'll use it as a preloader
    public class Main extends Sprite{

        [Embed(source="asset.swf")] //big asset to preload
        var assetClass:Class;

        public function Main(){
            // constructor code
        }
    }
}

In short, this tells the compiler to separate the .swf into two frames, one for the preloader, and the other for the application.

Now we need to create the preloader class to actually preload the game. An example of how this should be done:

package com.aierou.game{
    import flash.display.DisplayObject;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.utils.getDefinitionByName;

    public class Preloader extends MovieClip{ //should extend MovieClip for onEnterFrame action
        public function Preloader() {
            stop();
            addEventListener(Event.ENTER_FRAME,onEnterFrame);
        }

        public function onEnterFrame(e:Event){
            var total:Number = this.stage.loaderInfo.bytesTotal;
            var loaded:Number = this.stage.loaderInfo.bytesLoaded;
            if(total==loaded){
                removeEventListener(Event.ENTER_FRAME,onEnterFrame);
                nextFrame();
                init();
            }else{
                //show preloader progress
            }
        }

        private function init(){
            //Add the main class to the stage it's done this way to prevent the compiler from sticking embeds at the start
            var mainClass:Class=Class(getDefinitionByName("Container"));
            if(mainClass){
                var app:Object=new mainClass();
                addChild(app as DisplayObject);
            }
        }
    }
}

Now that we've got the main class and preloader set up, we're ready to compile our project. This is where the Flex SDK comes in. We'll be using the command line for this part, so adding the SDK bin folder to your "path" environment variable is recommended. Best practice involves setting up a .bat file in the project's root directory, making it easier to compile your project. The .bat I use is set up like so:

mxmlc -frame two Main -- Main.as
start /wait Main.swf

mxmlc will compile your project, putting the main class in a new frame labelled "two". The Frame tag in the main class will also force the compiler to put the preloader in the first frame.

If you don't get any compiler errors: Congratulations! You've added a true preloader to your project!

Try to add the Event.COMPLETE listener to the contentloaderInfo of the cs instance changing it

hsf8z42fdfd_as32.addEventListener(Event.COMPLETE, onComplete);

by

hsf8z42fdfd_as32.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top