我正在尝试预加载具有嵌入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);
}
似乎在文件实际加载后,进度函数只运行一次。进度事件应该在加载时运行,然后为什么不运行?
答案 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);