在游戏开发的过程中,经常需要将游戏资源放在外部swf中。本文讨论的就是在使用AS3载入外部的资源swf,并将其中的资源转换为类定义时要注意的一些东西。
我建立了两个swf,一个为LoadAppDomain.swf,一个为B.swf,用前者载入后者。后者定义在sub包中,并使用draw API绘制了一个红色圆形,同时定义了一个公共的bTrace方法。B.as代码如下:
在LoadAppDomain.as的构造函数中中,分别建立了Loader、URLLoader和URLStream的实例,并将它们的Complete事件指向同一个处理函数,如下:
这三个对象对于载入完成后的处理是不同的。其中Loader的处理最为直接。
1.如果只是需要将B.swf显示出来,则直接将_loader.content加入显示列表即可。同时也可以执行bTrace方法,在B的构造函数中的trace语句,会在complete完成的时候自动执行,无论我们是否将其加入了显示列表。而只有将_loader.content加入了显示列表后,B的stage才不为空。
2.如果需要获取载入的swf中的类定义,继续往下读。
如果使用URLLoader载入外部swf,则需要使用_urlLoader.dataFormat语句将载入的值设定为二进制格式,待载入完毕后,再使用_loader.loadBytes载入二进制数据。
如果使用URLStream载入外部swf则没有这个限制,URLStream默认载入的就是二进制数据流。在载入完成后,可以使用readBytes方法swf的二进制数据读入一个ByteArray对象中,然后再交给_loader.loadBytes载入。
在_loader.loadBytes完毕后,可以使用ApplicationDomain(应用程序域)对象的getDefinition方法获取类定义。如何使用ApplicationDomain,取决于载入swf的时候,将其放置于哪个应用程序域。详见 使用应用程序域
1.在使用_loader.loadBytes的时候,如果没有提供第二个参数,或者第二个参数为空,则默认将其载入自己的应用程序域,这样在获取类定义的时候,就需要使用下面的方法来获取类定义:
2.在使用_loader.loadBytes的时候,提供第二个参数,并将其设置成为当前域(ApplicationDomain.currentDomain):
那么,就需要用下面的方法来获取类定义:
获取类定义后,就可以实例化,并调用实例的方法。如果B与LoadAppDomain在同一个项目中,要注意不要在LoadAppDomian中出现B的定义,否则编译器会将B也编译进入LoadAppDomain中,会无谓的增加文件大小。
通过这个例子,也可以发现,被载入的swf在没有加入显示列表前是没有stage的,也就是说,被载入的swf使用的是载入它的swf的stage。在一个Flash Player中,只有一个stage存在。
我建立了两个swf,一个为LoadAppDomain.swf,一个为B.swf,用前者载入后者。后者定义在sub包中,并使用draw API绘制了一个红色圆形,同时定义了一个公共的bTrace方法。B.as代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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
)
;
}
}
}
|
在LoadAppDomain.as的构造函数中中,分别建立了Loader、URLLoader和URLStream的实例,并将它们的Complete事件指向同一个处理函数,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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
)
;
|
这三个对象对于载入完成后的处理是不同的。其中Loader的处理最为直接。
1.如果只是需要将B.swf显示出来,则直接将_loader.content加入显示列表即可。同时也可以执行bTrace方法,在B的构造函数中的trace语句,会在complete完成的时候自动执行,无论我们是否将其加入了显示列表。而只有将_loader.content加入了显示列表后,B的stage才不为空。
2.如果需要获取载入的swf中的类定义,继续往下读。
1
2
3
4
5
|
private
function
complete_handler
(
evt
:
Event
)
:
void
{
addChild
(
_loader
.
content
)
;
Object
(
_loader
.
content
)
.
bTrace
(
)
;
}
|
如果使用URLLoader载入外部swf,则需要使用_urlLoader.dataFormat语句将载入的值设定为二进制格式,待载入完毕后,再使用_loader.loadBytes载入二进制数据。
1
2
3
4
|
private
function
complete_handler
(
evt
:
Event
)
:
void
{
_loader
.
loadBytes
(
_urlLoader
.
data
as
ByteArray
)
;
}
|
如果使用URLStream载入外部swf则没有这个限制,URLStream默认载入的就是二进制数据流。在载入完成后,可以使用readBytes方法swf的二进制数据读入一个ByteArray对象中,然后再交给_loader.loadBytes载入。
1
2
3
4
5
6
|
private
function
complete_handler
(
evt
:
Event
)
:
void
{
var
__bytes
:
ByteArray
=
new
ByteArray
(
)
;
_urlStream
.
readBytes
(
__bytes
)
;
_loader
.
loadBytes
(
__bytes
)
;
}
|
在_loader.loadBytes完毕后,可以使用ApplicationDomain(应用程序域)对象的getDefinition方法获取类定义。如何使用ApplicationDomain,取决于载入swf的时候,将其放置于哪个应用程序域。详见 使用应用程序域
1.在使用_loader.loadBytes的时候,如果没有提供第二个参数,或者第二个参数为空,则默认将其载入自己的应用程序域,这样在获取类定义的时候,就需要使用下面的方法来获取类定义:
1
|
var
__B
:
Class
=
_loader
.
contentLoaderInfo
.
applicationDomain
.
getDefinition
(
'sub.B'
)
as
Class
;
|
2.在使用_loader.loadBytes的时候,提供第二个参数,并将其设置成为当前域(ApplicationDomain.currentDomain):
1
2
|
var
__context
:
LoaderContext
=
new
LoaderContext
(
false
,
ApplicationDomain
.
currentDomain
)
;
_loader
.
loadBytes
(
__bytes
)
;
|
那么,就需要用下面的方法来获取类定义:
1
|
var
__B
:
Class
=
ApplicationDomain
.
currentDomain
.
getDefinition
(
'sub.B'
)
as
Class
;
|
获取类定义后,就可以实例化,并调用实例的方法。如果B与LoadAppDomain在同一个项目中,要注意不要在LoadAppDomian中出现B的定义,否则编译器会将B也编译进入LoadAppDomain中,会无谓的增加文件大小。
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存在。