【问题标题】:Preloading swf which has embed source预加载嵌入源的 swf
【发布时间】:2012-09-10 23:30:03
【问题描述】:

我正在尝试预加载具有嵌入 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);
        }


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

【问题讨论】:

    标签: actionscript-3 embed flash preloading


    【解决方案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 文件夹添加到您的“路径”环境变量中。最佳实践包括在项目的根目录中设置一个 .bat 文件,以便更轻松地编译您的项目。我使用的 .bat 是这样设置的:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      这意味着一旦包含嵌入对象的类将由类加载器加载(在内存中),您将同时拥有它的所有依赖项(包括嵌入对象)。并且只有在执行完里面的代码之后,才看不到加载的进度。

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

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

      M.

      【讨论】:

      • 在应用程序中看到该方法,开发人员这样做了。使用了嵌入源,并且仍然.. 他/她预加载了主 swf....(嵌入了另一个 swf)
      • 你是在做flash还是flex?如果您使用 flash,则必须注意在舞台的第一帧中添加代码 new MainShell()。 Flash 将开始执行此代码,即使它尚未加载整个 swf(这可能是您所期望的)。注意:如果您在本地进行测试,由于加载时间非常短,您可能会遇到一些困难。您应该模拟慢速连接以确保其正常工作。
      • 我使用的是 Flash,而 MainShell 是文档类,因此它可以运行。调试面板中有一个“模拟下载”选项,我可以在其中以自定义速度模拟下载。我做了一个测试,它奏效了。 Main.swf 在具有嵌入源 swf 的同时完美预加载...但我仍然无法制作另一个嵌入任何 swf 的 .fla 和 .swf...出了点问题。
      • 我不确定。在您的问题中,您说它“预加载具有嵌入 swf (...) 但它不想工作的 swf”不起作用,并且在之前的评论中:“Main.swf 完美预加载”...请查看您的帖子,提供您的 swf、fla 的架构以及哪些不完全有效。
      • Main.swf 是 MainShell.swf 嵌入的内容。如果我在 Main.swf 中嵌入了一些东西,然后为它做一个预加载,那么它就可以工作了。当我对 MainShell.swf 做同样的事情时。它不起作用。它有相同的脚本,一切都是一样的。 .fla 除外。
      【解决方案3】:

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

      hsf8z42fdfd_as32.addEventListener(Event.COMPLETE, onComplete);
      

      通过

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

      【讨论】:

      • 对不起,我没看懂你的问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-27
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 1970-01-01
      • 2013-03-08
      相关资源
      最近更新 更多