预加载嵌入源的swf

时间:2012-09-18 16:46:05

标签: actionscript-3 embed flash preloading

我正在尝试预加载具有嵌入swf源的swf。但它不想工作。我尝试了简单的预加载,但进度事件仅在加载后运行。有什么想法吗?

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


似乎在文件实际加载后,进度函数只运行一次。进度事件应该在加载时运行,然后为什么不运行?

3 个答案:

答案 0 :(得分:2)

您无法预加载嵌入对象。嵌入对象的概念是它们随容器一起提供。

这就好像您的MainShell包含Main.swf。

这意味着只要包含嵌入对象的类将由类加载器加载(在内存中),您将同时拥有其所有依赖项(包括嵌入对象)。只有在那之后执行内部代码,这就是你无法看到加载进度的原因。

内容加载器用于从服务器加载远程内容。有了这个,您将看到HTTP GET请求的进度(如果它还没有在浏览器缓存中)。

如果要显示加载进度条等,则不得使用嵌入内容。

HIH

微米。

答案 1 :(得分:1)

我已经回到这里分享我对这个问题的解决方案。

这实际上是可行的。但是,如果您的项目使用库资产或时间轴代码,则解决方案将无法轻松工作。该解决方案要求您的项目主要存在于AS3类中,因此您可能必须调整代码才能使其正常工作。

首先,您需要下载Flex SDK(http://www.adobe.com/devnet/flex/flex-sdk-download.html)。您将使用它将您的as3类编译为.swf(Flex不会弄乱您的项目,不用担心)。我们将在初始设置后再回过头来看。

现在,我们将使用Flex SDK的未记录技巧:Frame元数据标记。 http://www.bit-101.com/blog/?p=946上的博客更详细,但Frame标签基本上允许您嵌入类而不会在以后调用它们,而不是对任何代码/嵌入进行操作。我们将在包定义之后但在Main类的类定义之前坚持这一点,如下所示:

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
        }
    }
}

简而言之,这告诉编译器将.swf分成两个帧,一个用于预加载器,另一个用于应用程序。

现在我们需要创建预加载器类来实际预加载游戏。如何做到这一点的一个例子:

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

现在我们已经设置了主类和预加载器,我们已经准备好编译我们的项目了。这就是Flex SDK的用武之地。我们将使用此部分的命令行,因此建议将SDK bin文件夹添加到“path”环境变量中。最佳实践涉及在项目的根目录中设置.bat文件,以便更轻松地编译项目。我使用的.bat设置如下:

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

mxmlc将编译您的项目,将主类放在标记为“two”的新框架中。主类中的Frame标记也会强制编译器将预加载器放在第一帧中。

如果您没有收到任何编译器错误:恭喜!您已为项目添加了一个真正的预加载器!

答案 2 :(得分:0)

尝试将Event.COMPLETE侦听器添加到更改 cs 实例的contentloaderInfo

hsf8z42fdfd_as32.addEventListener(Event.COMPLETE, onComplete);

通过

hsf8z42fdfd_as32.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);