【问题标题】:Preloader in actionscript 3 - Reference Error on getDefinition()actionscript 3 中的预加载器 - getDefinition() 上的引用错误
【发布时间】:2009-11-17 23:13:23
【问题描述】:

我正在写一个预加载器:

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) 进行编译。我错过了什么明显的东西吗?

【问题讨论】:

    标签: actionscript-3 preloader


    【解决方案1】:

    当您以这种“风格”制作预加载器时,实际发生的情况是预加载器被放置在应用程序的第一帧中,而其余部分则在第二帧中。您在这里缺少的是告诉编译器您希望在其中编译 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() 命令也是一个好主意,只是为了让播放头不会搞砸,但这确实是以后的问题。

    【讨论】:

    • 酷!我不知道。我希望这能解决蒂米的问题
    • 不幸的是,我已经这样做了。当我说“我使用 frames.frame 插入 Main”时,我并不清楚。
    • 不,不走运。我想知道是否涉及某种时间安排 - 我添加了一个带有 onclick 的“开始”按钮,它每次都有效。尽管如此,仍然试图避免走那条路,上面的内容非常简单。
    • 该代码似乎也可以在 FlashDevelop 中工作,但当我直接从 mxmlc 中执行时却不行。奇数。
    • 是的,我也在想同样的事情。我重写了它(作为电影剪辑)并检查帧,现在它似乎工作正常。谢谢!
    【解决方案2】:

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

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

    另外,如果你使用 Event.INIT 而不是 Event.COMPLETE 有什么不同吗?

    【讨论】:

    • 移动包 = 相同的结果。我将根作为变量传递给类(所以我可以读取 flashvars) Event.INIT 没有改变任何东西。谢谢。
    • 游戏类是公开的吗?另外,这方便吗:kirupa.com/forum/showthread.php?t=274871
    • 是的,它是公开的。我发现如果我添加了一个按钮或一个计时器,它似乎可以找到它。就好像它在实际准备好之前触发了事件..
    • 感谢您的链接,但不行.. =(
    【解决方案3】:

    你缺少 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);
        }
        }
    

    【讨论】:

      【解决方案4】:

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

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

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

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

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

      简而言之:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-08
        • 2011-09-05
        相关资源
        最近更新 更多