您的位置:首页 > 其它

使用Loader/URLLoader/URLStream载入外部swf并获取类定义

2014-03-27 14:19 148 查看
在游戏开发的过程中,经常需要将游戏资源放在外部swf中。本文讨论的就是在使用AS3载入外部的资源swf,并将其中的资源转换为类定义时要注意的一些东西。

我建立了两个swf,一个为LoadAppDomain.swf,一个为B.swf,用前者载入后者。后者定义在sub包中,并使用draw API绘制了一个红色圆形,同时定义了一个公共的bTrace方法。B.as代码如下:

package sub
{
import flash.display.Sprite;
import flash.events.Event;

public class B extends Sprite
{
public function B()
{
trace('B init');
graphics.beginFill(0xff0000);
graphics.drawCircle(100,100, 50);
graphics.endFill();
this.addEventListener(Event.ADDED_TO_STAGE, function():void{trace('B add to stage');});
}

public function bTrace():void
{
trace('B trace');
trace('B.stage:', stage);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

packagesub

{
importflash.display.Sprite;

import flash.events.Event;

publicclassBextendsSprite
{

publicfunctionB()
{

trace('B init');
graphics.beginFill(0xff0000);

graphics.drawCircle(100,100,50);
graphics.endFill();

this.addEventListener(Event.ADDED_TO_STAGE,function():void{trace('B
add to stage');});
}

publicfunctionbTrace():void

{
trace('B trace');

trace('B.stage:',stage);
}

}
}

在LoadAppDomain.as的构造函数中中,分别建立了Loader、URLLoader和URLStream的实例,并将它们的Complete事件指向同一个处理函数,如下:

var __request:URLRequest = new URLRequest('B.swf');
trace('LoadAppDomain init');
this.addEventListener(Event.ADDED_TO_STAGE, function():void{trace('LoadAppDomain added to stage');});

_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, complete_handler);
_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progress_handler);
//_loader.load(__request);

_urlStream = new URLStream();
_urlStream.addEventListener(HTTPStatusEvent.HTTP_STATUS, http_statusHandler);
_urlStream.addEventListener(Event.COMPLETE, complete_handler);
_urlStream.addEventListener(ProgressEvent.PROGRESS, progress_handler);
//_urlStream.load(__request);

_urlLoader = new URLLoader();
_urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
_urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, http_statusHandler);
_urlLoader.addEventListener(Event.COMPLETE, complete_handler);
_urlLoader.addEventListener(ProgressEvent.PROGRESS, progress_handler);
_urlLoader.load(__request);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

var__request:URLRequest=newURLRequest('B.swf');

trace('LoadAppDomain init');
this.addEventListener(Event.ADDED_TO_STAGE,function():void{trace('LoadAppDomain
added to stage');});

_loader=newLoader();

_loader.contentLoaderInfo.addEventListener(Event.COMPLETE,complete_handler);
_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progress_handler);

//_loader.load(__request);

_urlStream =newURLStream();
_urlStream.addEventListener(HTTPStatusEvent.HTTP_STATUS,http_statusHandler);

_urlStream.addEventListener(Event.COMPLETE,complete_handler);
_urlStream.addEventListener(ProgressEvent.PROGRESS,progress_handler);

//_urlStream.load(__request);

_urlLoader =newURLLoader();
_urlLoader.dataFormat=URLLoaderDataFormat.BINARY;

_urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS,http_statusHandler);
_urlLoader.addEventListener(Event.COMPLETE,complete_handler);

_urlLoader.addEventListener(ProgressEvent.PROGRESS,progress_handler);
_urlLoader.load(__request);

这三个对象对于载入完成后的处理是不同的。其中Loader的处理最为直接。

1.如果只是需要将B.swf显示出来,则直接将_loader.content加入显示列表即可。同时也可以执行bTrace方法,在B的构造函数中的trace语句,会在complete完成的时候自动执行,无论我们是否将其加入了显示列表。而只有将_loader.content加入了显示列表后,B的stage才不为空。

2.如果需要获取载入的swf中的类定义,继续往下读。

private function complete_handler(evt:Event):void
{
addChild(_loader.content);
Object(_loader.content).bTrace();
}

1
2
3
4
5

privatefunctioncomplete_handler(evt:Event):void

{
addChild(_loader.content);

Object(_loader.content).bTrace();
}

如果使用URLLoader载入外部swf,则需要使用_urlLoader.dataFormat语句将载入的值设定为二进制格式,待载入完毕后,再使用_loader.loadBytes载入二进制数据。

private function complete_handler(evt:Event):void
{
_loader.loadBytes(_urlLoader.data as ByteArray);
}

1
2
3
4

privatefunctioncomplete_handler(evt:Event):void

{
_loader.loadBytes(_urlLoader.data as ByteArray);

}

如果使用URLStream载入外部swf则没有这个限制,URLStream默认载入的就是二进制数据流。在载入完成后,可以使用readBytes方法swf的二进制数据读入一个ByteArray对象中,然后再交给_loader.loadBytes载入。

private function complete_handler(evt:Event):void
{
var __bytes:ByteArray = new ByteArray();
_urlStream.readBytes(__bytes);
_loader.loadBytes(__bytes);
}

1
2
3
4
5
6

privatefunctioncomplete_handler(evt:Event):void

{
var__bytes:ByteArray=newByteArray();

_urlStream.readBytes(__bytes);
_loader.loadBytes(__bytes);

}

在_loader.loadBytes完毕后,可以使用ApplicationDomain(应用程序域)对象的getDefinition方法获取类定义。如何使用ApplicationDomain,取决于载入swf的时候,将其放置于哪个应用程序域。详见使用应用程序域

1.在使用_loader.loadBytes的时候,如果没有提供第二个参数,或者第二个参数为空,则默认将其载入自己的应用程序域,这样在获取类定义的时候,就需要使用下面的方法来获取类定义:

var __B:Class = _loader.contentLoaderInfo.applicationDomain.getDefinition('sub.B') as Class;

1

var__B:Class=_loader.contentLoaderInfo.applicationDomain.getDefinition('sub.B')asClass;

2.在使用_loader.loadBytes的时候,提供第二个参数,并将其设置成为当前域(ApplicationDomain.currentDomain):

var __context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
_loader.loadBytes(__bytes );

1
2

var__context:LoaderContext=newLoaderContext(false,ApplicationDomain.currentDomain);

_loader.loadBytes(__bytes);

那么,就需要用下面的方法来获取类定义:

var __B:Class = ApplicationDomain.currentDomain.getDefinition('sub.B') as Class;

1

var__B:Class=ApplicationDomain.currentDomain.getDefinition('sub.B')asClass;

获取类定义后,就可以实例化,并调用实例的方法。如果B与LoadAppDomain在同一个项目中,要注意不要在LoadAppDomian中出现B的定义,否则编译器会将B也编译进入LoadAppDomain中,会无谓的增加文件大小。

Object(_loader.content).bTrace();
var __b2:* = new __B();
addChild(__b2);
__b2.bTrace();
trace(__b2.stage == stage);

1
2
3
4
5

Object(_loader.content).bTrace();

var __b2:*=new__B();
addChild(__b2);

__b2.bTrace();
trace(__b2.stage==stage);

通过这个例子,也可以发现,被载入的swf在没有加入显示列表前是没有stage的,也就是说,被载入的swf使用的是载入它的swf的stage。在一个Flash Player中,只有一个stage存在。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: