3

我正在写一个预加载器:

package {
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.display.LoaderInfo;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.system.System;

    public class Preloader extends Sprite {
            private var t:TextField = new TextField();
            private var ver:String = "1000";
            public function Preloader() {
                    t.y = 570;
                    addChild( t );
                    t.text = ver;

                    addEventListener( Event.ADDED_TO_STAGE, init );
            }

            private function init( e:Event ):void {
                    this.root.loaderInfo.addEventListener( ProgressEvent.PROGRESS, onLoadingProgress );
                    this.root.loaderInfo.addEventListener( Event.COMPLETE, onLoadingCompleted );

                    // See if it's already completed
                    var percent:int = int( root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal );
                    if ( percent == 1 )
                            onLoadingCompleted();
            }

            private function onLoadingProgress( event:Event ):void {
                    var percent:int = int(root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal * 100);
                    t.text = "Loading.. " + percent + "%";
            }

            private function onLoadingCompleted( event:Event = null ):void {
                    root.loaderInfo.removeEventListener( ProgressEvent.PROGRESS, onLoadingProgress );
                    root.loaderInfo.removeEventListener( Event.COMPLETE, onLoadingCompleted );

                    var mainClass:Class = loaderInfo.applicationDomain.getDefinition("Main") as Class;
                    var main:DisplayObject = new mainClass() as DisplayObject;

                    parent.addChild( main );
                    parent.removeChild( this );
            }
    }
}

以此作为主类:

package {
    import flash.display.Sprite;

    public class Main extends Sprite {

            public function Main() {
            }
    }
}

所以这几乎是我能做到的准系统。

但是,它向我打招呼:

ReferenceError: Error #1065: Variable Main is not defined.
at flash.system::ApplicationDomain/getDefinition()
at ...

我已经使用 frames.frame 来插入 Main 了。我正在直接使用 ant 和 linux SDK (mxmlc) 进行编译。我错过了什么明显的东西吗?

4

4 回答 4

4

当你以这种“风格”制作预加载器时,真正发生的是预加载器被放在应用程序的第一帧中,其余的在第二帧中。您在这里缺少的是告诉编译器您希望在其中编译 Main 类,因此现在它甚至不存在于 swf 中。这就是 getDefinition 不起作用的原因。

您也不能简单地在预加载器中引用它,因为这会使它在显示预加载器之前加载到第一帧中。所以,你需要一点自定义参数魔法。

将此行添加到您的编译器选项中,您应该很高兴:

-frame start Main

请记住,如果您的 Main 类在一个包中,您需要在其中获得完整的参考:

-frame start com.grapefrukt.examples.Main

getDefinition 调用也是如此。

编辑:

在查看执行此操作的代码时,我发现我使用了与您所做的不同的方法,也许这会更好:

var mainClass:Class = getDefinitionByName("com.grapefrukt.examples.Main") as Class;
addChild(new mainClass() as DisplayObject);

再次编辑:如果它使用按钮工作,我猜由于某种原因,完整事件被触发得太早了。尽管加载了所有字节,但可能导致一切都没有正确启动。尝试使用此代码检查是否完成:

if (currentFrame == totalFrames) onLoadingCompleted()

在你的 onLoadingCompleted() 方法中添加一个 stop() 命令也可能是一个好主意,只是为了让播放头不会搞砸,但这确实是后来的问题。

于 2009-11-18T09:18:47.547 回答
1

如果您在默认包中有 Game 类(“Game”而不是“game.Game”),有什么不同吗?

我从来没有使用过 new mainClass(this.root) 之类的东西,new mainClass() 应该没问题。

另外,如果您使用 Event.INIT 而不是 Event.COMPLETE 有什么区别吗?

于 2009-11-17T23:33:17.093 回答
1

你错过了 nextFrame();
在 onLoadingComplete 函数中添加 nextFrame();

这是一个简单的版本:

    public class Preloader extends MovieClip 
    {
    public function Preloader() 
    {
        stop();
        addEventListener(Event.ENTER_FRAME, onEnterFrame);
        this.loaderInfo.addEventListener(Event.COMPLETE, startup);
        // Set up progress bar / graphics
    }

    private function onEnterFrame(e:Event):void 
    {
        // Display progress bar, loadedbytes, animation, etc...
    }

    private function startup(e:Event):void 
    {
        nextFrame();
        removeEventListener(Event.ENTER_FRAME, onEnterFrame);
        loaderInfo.removeEventListener(Event.COMPLETE, startup);
        var gameClass:Class = getDefinitionByName("Main") as Class;
        if (gameClass) addChild(new gameClass() as Sprite);
    }
    }

于 2011-09-10T00:10:34.400 回答
1

评论有点长,尽管它实际上是对grapefrukt答案的扩展。这也是一个相当晚的答案。但我还没有看到 Adob​​e 或其他任何人在任何地方记录过这一点:

Event.COMPLETE可能似乎“提前”触发的一个原因(在下一帧实际准备好之前)是在使用运行时共享库​​时。Event.COMPLETE将在当前 swf 完成加载时触发 - 这可能(并且通常会)在任何 RSL 完成加载之前发生。

RSL 的“自动”加载(例如,在 Flash Pro 中使用“导入用于运行时共享”)将在加载链接到它们的库符号时加载,这 - 在通常的预加载器实现中 - 意味着当播放头尝试进入第 2 帧时。

在它们完成加载之前,您无法前进到第 2 帧 - 只要您无法前进,您将无法访问该帧上的任何类或实例。任何呼叫gotoAndStop(2)nextFrame()不会立即产生任何效果(即,eLouai 的回答在这种情况下不起作用),而且,呼叫也不会被“排队”。播放头将简单地停留在第 1 帧上。可能是在内部发生了一些参考错误,这些错误在 FlashPlayer 的某个地方被吞没了。至少在我的测试中,从未报告过错误。它只是默默地失败。play()但是,转到下一帧 - 当它准备好时。

换句话说 - 正如grapefrukt 建议的那样 - 如果正在播放 swf,您可以在侦听器中等待currentFrame == 2(或任何帧号) 。ENTER_FRAME或者,您可以在侦听器中调用nextFrame()or gotoAndStop(2)(或任何帧号),ENTER_FRAME直到检测到currentFrame == 2. 后者似乎在未来可能会中断,因为尽管玩家没有输出任何错误,但实际上可能在内部发生错误。

简而言之:

play()将等到第 2 帧准备好。gotoAndStop(2)or nextFrame()will (appear to) 没有任何效果,除非第 2 帧在被调用时准备好。并且Event.COMPLETE不保证所有帧都准备好显示。特别是如果使用 RSL,则不会 - 可能还有其他原因。

于 2012-11-18T17:44:08.487 回答