Actionscript 3 actionscript 3中的预加载程序-getDefinition()上的引用错误

Actionscript 3 actionscript 3中的预加载程序-getDefinition()上的引用错误,actionscript-3,preloader,Actionscript 3,Preloader,我正在写一个预加载程序: 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.

我正在写一个预加载程序:

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)进行编译。我是否遗漏了任何明显的内容?

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

我从未使用过像new mainClass(this.root)这样的东西,new mainClass()应该可以


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

当您以这种“样式”制作预加载程序时,真正发生的是预加载程序放在应用程序的第一个帧中,其余的放在第二个帧中。这里缺少的是告诉编译器您希望编译主类,所以现在它甚至不存在于swf中。这就是为什么getDefinition不起作用

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

将这一行添加到编译器选项中,您就可以开始了:

-frame start Main
请记住,如果主类位于包中,则需要在其中获取完整引用:

-frame start com.grapefrukt.examples.Main
getDefinition调用也是如此

编辑:

当查看我的代码时,我发现我使用了与您不同的方法,也许这更有效:

var mainClass:Class = getDefinitionByName("com.grapefrukt.examples.Main") as Class;
addChild(new mainClass() as DisplayObject);
再次编辑: 如果它使用一个按钮工作,我猜由于某种原因,整个事件触发得太早了。虽然所有的字节都是loaderd,但可能所有的事件都没有正确初始化。请尝试使用此代码检查是否完成:

if (currentFrame == totalFrames) onLoadingCompleted()
在onLoadingCompleted()方法中添加一个stop()命令可能也是一个好主意,只是为了使playhead不会把事情搞砸,但这确实是后面的问题。

您缺少nextFrame()
在函数onLoadingComplete中添加nextFrame()

下面是一个简单的版本:


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

使用运行时共享库时,
Event.COMPLETE
可能会“提前”(在下一帧实际就绪之前)触发的一个原因是<代码>事件。完成将在当前swf完成加载时触发-这可能(通常)发生在任何RSL完成加载之前

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

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

换句话说,正如grapefrukt建议的那样,如果swf正在播放,您可以在
输入帧
侦听器中等待
currentFrame==2
(或任何帧编号)。或者,您可以在
ENTER\u frame
侦听器中调用
nextFrame()
gotoAndStop(2)
(或任何帧编号),直到检测到
currentFrame==2
。后者看起来像是未来可能发生的事情,因为,同样,错误实际上可能是在内部发生的,尽管玩家没有输出任何错误

简言之:


play()
将等待第2帧准备就绪
gotoAndStop(2)
nextFrame()
将(看起来)没有任何效果,除非调用时frame 2已准备就绪。和
Event.COMPLETE
不能保证所有帧都已准备好显示。特别是如果使用RSL,则不会这样做-可能还有其他原因。

移动包=相同的结果。我将根作为变量传递给类(以便读取flashvars)Event.INIT没有更改任何内容。谢谢。集体游戏是公开的吗?还有,这方便吗?是的,这是公共的。我发现,如果我添加了一个按钮或计时器,它似乎找到了它。这几乎就像它在实际准备就绪之前触发事件一样..谢谢链接,但不可以=(酷!我不知道。我希望这能解决Timmy的问题。不幸的是,我已经这么做了。当我说“我使用frames.frame插入Main”时,我不清楚。不,运气不好。我想知道是否涉及到一些计时问题-我加了一个“开始”用onclick按钮,每次都有效。但仍然试图避免走这条路,上面的代码非常简单。该代码在FlashDevelop中似乎也能工作,但在我直接从mxmlc中执行时就不行了。奇怪。是的,我也在想同样的事情。我重写了它(作为电影剪辑)检查一下镜框,现在看起来还可以了。谢谢!
    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);
    }
    }