2023年12月17日发(作者:)

动画制作技巧:如何加载外部SWF文件

一、控制影片剪辑

影片剪辑是Flash中最重要的一种元件,对影片剪辑的控制是ActionScript的最重要功能之一。从根本上说,Flash的许多复杂动画效果和交互功能都与影片剪辑的运用密不可分。

使用点语法或方括号可以定位影片剪辑。使用方括号时可以使用由变量表示的影片剪辑实例名,这是它相对于点语法的优点。

可以用脚本控制影片剪辑的各种动作,也可以在影片剪辑的事件处理函数中控制主时间轴和别的影片剪辑。影片剪辑最重要的两个事件是load和enterFrame。

1控制影片剪辑的播放动作

设想一个Flash动画,它的主场景中只有一个帧,舞台中只有一个影片剪辑,影片剪辑中并没有ActionScript。如何才能控制影片剪辑的播放动作呢?

要控制一个影片剪辑,首先应该为影片剪辑命名。容易混淆的是,库面板中的影片剪辑本身有一个名称,这里要命名的是场景中影片剪辑实例的名称。它们可以相同,也可以不相同。如果你在场景中创建了同样的影片剪辑的多个实例,那么就需要将每个实例以不同的名称命名,才能用ActionScript对每一个实例进行控制。如果不需要对影片剪辑进行控制,也就不需要为影片剪辑的实例命名。

从本例文件中,你将看到库面板中只有一个影片剪辑rollmc,场景中创建了一个rollmc的实例。你还可以再从库中拖出若干个rollmc的实例将它们放置到场景中。

选中场景中影片剪辑rollmc的实例,打开属性面板,可以看到它被命名为roll,你同时可以看到该影片剪辑原来的名字rollmc,如图5-1所示。你也可以为它指定别的名称,也可以是rollmc,Flash并不会混淆它们之间的区别。

实例名称可以在程序中用来指代该影片剪辑实例,如果要控制该实例,就需要在脚本中使用该名称。下面,我们就来看看如何通过脚本控制影片剪辑实例roll。

分别选中场景中的4个按钮,打开它们的动作面板,查看其中的代码。

“STOP”按钮:

on (release) {

();

}

单击“STOP”按钮使roll实例停止播放。

“PLAY”按钮:

on (release) {

();

}

单击“PLAY”按钮使roll实例继续播放。

“PREV”按钮:

on (release) {

ame();

}

单击“PREV”按钮使roll实例回退一帧并停止。

“NEXT”按钮:

on (release) {

ame();

}

单击“NEXT”按钮使roll实例播放一帧并停止。

按Ctrl+Enter键测试影片,如图5-2所示。一开始影片剪辑自动播放。单击不同的按钮看看影片剪辑是否执行相应的动作。

除了这几种命令,你还可以使用gotoAndStop或gotoAndPlay命令控制影片剪辑跳转到具体的帧,但是在命令前面都需要指定影片剪辑的实例名称。

这种方法是在影片剪辑实例所在的层级中控制影片剪辑,如果是在影片剪辑内部,要控制它自身的播放,就可以直接使用stop、play等命令,而不需要指定实例名称。如果你在影片剪辑内部的时间轴中使用了名称roll,Flash会在影片剪辑内部的时间轴中寻找该实例。

2定位影片剪辑

我们已经了解了如何使用最简单的方法定位一个影片剪辑,即使用影片剪辑的实例名,后面紧跟一个点记号“.”,然后是你想要影片剪辑执行的命令。

还有许多方法可以定位影片剪辑。首先,我们来看看如何定位Flash影片中不同层级的对象。

Flash影片中最基本的目标层级就是它的主时间轴。可以用关键字_root来表示和定位主时间轴。

例如,你要向主时间轴发送一个gotoAndStop命令,可以使用如下所示的语句:

_dStop(9);

如果这个命令是包含在主时间轴的某一帧上的,则可以省略目标_root。如果这个命令是包含在主时间轴上某个影片剪辑中,需要由影片剪辑来控制它上一级的主时间轴,_root就很有必要了。

通常,要定位包含某一对象的上一级对象,可以使用关键字_parent。所以,如果一个影片剪辑是包含在主时间轴中,在影片剪辑中使用_parent和_root的效果是一样的。如果影片剪辑与主时间轴相差两个层级,即当影片剪辑包含在另一个位于主时间轴中的影片剪辑中,这时在该影片剪辑中使用_parent指代的是它上一级的影片剪辑,而_root是指它上两级的主时间轴。在主时间轴中不能使用_parent,因为主时间轴没有上一级。

可以用数字来方便地说明这种层级关系。主时间轴,它始终是最初级,作为层级0。主时间轴中的一个影片剪辑处于层级1。如果影片剪辑中包含另一个影片剪辑,它处于层级2。对层级2上的影片剪辑来说,_parent指代的就是层级1上的影片剪辑,而不管对哪一级来说,_root始终指代层级0上的主时间轴。

除了用点记号连接_root和实例名,还可以使用方括号表示_root上的对象。对上例中的按钮“stop”来说,如下所示的3种方法作用是一样的:

();

_();

_root["roll"].stop();

还有一个关键字this,它代表脚本当前所在的层级。如果脚本位于主时间轴中,this即指代主时间轴;如果脚本位于影片剪辑中,this即指代该影片剪辑。所以以上语句还可以用以下两种方式表示:

();

this["roll"].stop();

使用_root和this时还可以用变量来定位影片剪辑,如下所示:

var mcInsName = "roll";

_root[mcInsName].stop();

今后我们会遇到这种情况,即有roll0~rool99共100个影片剪辑实例,可以使用下面的语句来控制它们:

on (release) {

for (var i = 0; i<100; i++) {

_root["roll"+i].stop();

}

}

多数情况下我们习惯使用_root,但在某些情况下使用this比_root更简便。如要在某个影片剪辑中定位包含 在此影片剪辑中的另一影片剪辑childMC,就可以直接使用C。

3为影片剪辑添加脚本

现在你已经知道如何向帧和按钮中添加脚本,下面需要知道如何向影片剪辑中添加脚本。

要为影片剪辑添加脚本,首先要选中影片剪辑,再打开它对应的动作面板,然后在其中输入脚本。影片剪辑脚本和按钮的脚本类似,它们都使用事件处理函数,与按钮的on关键字不同,影片剪辑使用onClipEvent关键字。当某种影片剪辑事件发生时,就会触发相应的事件处理函数。

影片剪辑最重要的两种事件是load和enterFrame。

load事件在影片剪辑完全加载到内存中时发生。在每次播放Flash影片时,每个影片剪辑的load事件只发生一次。

在主时间轴停止播放时,影片中的影片剪辑并不会停止播放,这个特性决定了影片剪辑的另一个事件enterFrame的重要性。enterFrame事件在影片每次播放到影片剪辑所在帧时发生。如果主时间轴中只有一帧,且不论它是否在该帧停止,该帧中的影片剪辑都会不断触发enterFrame事件,且触发的频率与Flash影片的帧频一致。

影片剪辑事件的使用方法如下所示:

onClipEvent (load) {

var i = 0;

}

onClipEvent (enterFrame) {

trace(i);

i++;

}

当影片剪辑的load事件发生时,将变量i设置为0。当影片剪辑的enterFrame事件发生时,向输出窗口中发送i的值,然后将i加1。输出窗口中会从0开始输出以1递增的数字序列,直到影片被关闭为止。

为了熟悉影片剪辑事件处理函数的用法,我们来为影片剪辑编写一段简单的脚本,使影片剪辑逆序播放,

我们将从影片剪辑的最后一帧处开始播放,使用prevFrame命令使影片剪辑每次后退一帧。

本例文件场景中有一个影片剪辑元件rollmc,查看一下它的属性面板,并没有为其实例命名,这是因为我们要直接在影片剪辑的动作面板中添加脚本,并不

需要用到实例名称。

选中影片剪辑rollmc,此时动作面板的标题栏中应为“动作-影片剪辑”。打开动作面板,其中添加了如下ActionScript:

onClipEvent (load) {

gotoAndStop(40);

}

onClipEvent (enterFrame) {

prevFrame();

}

在事件处理函数onClipEvent (load)中,令Flash影片的播放头转到影片剪辑的第40帧(即最后一帧)。这个事件处理函数只在影片剪辑被加载完成时执行1次。第2个事件处理函数onClipEvent (enterFrame)每播放1帧就执行1次,使影片剪辑回退1帧。

按Ctrl+Enter键测试影片,你将看到齿轮以与上例相反的方向转动,直到影片剪辑的时间轴回到第1帧,prevFrame命令不起作用,影片剪辑停止播放。要让它连续不断的播放,可以在影片剪辑元件rollmc的时间轴第1帧的动作面板中添加如下语句:

gotoAndStop(40);

4 用影片剪辑控制别的影片剪辑

一个影片剪辑可以控制别的影片剪辑。综合使用_root或_parent关键字、点符号和影片剪辑实例名称可以将命令发送给另一个影片剪辑实例。例如,在主时间轴上的影片剪辑实例roll1中添加如下脚本以控制同在主时间轴上的影片剪辑实例roll2回退1帧:

_ame();

或者使用方括号表示如下:

_root["roll2"].prevFrame();

如果两个影片剪辑不同在主时间轴上,而是同在别的层级上,可以使用_parent关键字。如果它们不同在一个层级上,也只需要使用点符号逐级标明所在的路径即可。

下面综合运用以上知识实现以影片剪辑控制另一个剪辑的播放动作。

(1)打开本例文件。分别查看场景中的每一层。按Ctrl+L打开库面板。库面板中有三个影片剪辑元件,分别是hour、minute和second。

(2)分别双击每个影片剪辑元件,查看它们的时间轴。

(3)second元件的的时间轴共60帧,secondhand图形元件顺时针旋转1周。在第1帧中添加了如下ActionScript:

stop();

在最后1帧中添加了如下ActionScript:

_root[target].nextFrame();

gotoAndStop(1);

(4)minute元件的的时间轴共60帧,minutehand图形元件顺时针旋转1周。在第1帧中添加了如下ActionScript:

stop();

在最后1帧中添加了如下ActionScript:

_root[target].nextFrame();

gotoAndStop(1);

(5)hour元件的的时间轴共12帧,hourhand图形元件顺时针旋转1周。在第1帧中添加了如下ActionScript:

stop();

(6)回到主场景,在属性面板中为hour影片剪辑和minute影片剪辑指定了与元件名称相同的实例名称。

(7)选中second元件实例,打开其动作面板,其中添加了如下ActionScript:

onClipEvent (load) {

target = "minute";

}

onClipEvent (enterFrame) {

nextFrame();

}

(8)选中minute元件实例,打开其动作面板,其中添加了如下ActionScript:

onClipEvent (load) {

target = "hour";

}

以上脚本的原理是:使每个影片剪辑都在各自的第1帧停止。在second的enterFrame事件中令其自身移到下一帧。直到second元件转动完一周,到达最后一帧,使用_root[target].nextFrame();命令将target所指目标后移1帧,这里的target是在second影片剪辑实例的load事件中定义的,也就是minute。同样,直到minute元件转动完一周到达最后1帧,使用_root[target].nextFrame();命令将target所指目标后移1帧,这里的target是在minute影片剪辑实例的load事件中定义的,也就是hour。

由于影片剪辑的转动是由nextFrame命令实现的,所以在每个元件内部时间轴的最后1帧中添加了跳转到第1帧的语句,避免停止在最后1帧上。

上面的ActionScript主要有两种,一种是在影片剪辑内部时间轴上的帧脚本,另一种是在主时间轴中的影片剪辑脚本。我们使用一个全局变量target记录影片剪辑实例名称,这个动作是在影片剪辑的事件处理函数中完成的,然后将这个全局变量应用到影片剪辑内部的帧脚本中。从这里也可以看到,影片剪辑动作和影片剪辑内部的帧动作是可以进行通信的,全局变量在它们之间有效,但在两个影片剪辑之间就变得无效,所以我们可以在两个影片剪辑中同时使用target而互不影响。

(9)按Ctrl+Enter测试影片。

二、影片剪辑属性

通过调整影片剪辑的各种属性可以改变影片剪辑的位置和显示状态。_x和_y属性代表影片剪辑在场景中的水平坐标和垂直坐标。_xscale和_width属性决定影片剪辑在水平方向上的显示宽度,_yscale和_height属性决定影片剪辑在垂直方向上的显示高度。使用_rotation属性可以旋转影片剪辑。_alpha属性代表影片剪辑的透明度,_visible属性决定影片剪辑是否可见。使用关键字_xmouse和_ymouse可以获取鼠标光标在屏幕中的坐标位置。

1 坐标

Flash场景中的每个对象都有它的坐标,坐标值以像素为单位。Flash场景的左上角为坐标原点,它的坐标位置为0,0,前一个0表示水平坐标,后一个0表示

垂直坐标。Flash默认的场景大小为550×400像素,即场景右下角的坐标为550,400,它表示距坐标原点的水平距离为550,垂直距离为400。场景中的每一点都可以用坐标表示.

习惯地,水平坐标用x表示,垂直坐标用y表示。在Flash中,分别用_x和_y表示x坐标值属性和y坐标值属性。例如,要在主时间轴上表示场景中的影片剪辑myMC的位置属性,可以使用下面的方法:

myMC._x

myMC._y

如果是在myMC自身的脚本中表示它的坐标,也以使用如下的方法:

_x;

_y;

或:

this._x;

this._y;

在属性面板和信息面板中都有可以查看和更改对象的位置。选择“窗口”→“信息”命令或按快捷键Ctrl+I都可以打开信息面板,如图6-2所示。

信息面板中显示了当前所选图形或影片剪辑的大小、坐标位置、颜色以及鼠标位置等。图6-2中信息面板右边的两个数值框X和Y代表了所选对象的水平坐标和垂直坐标。面板中的 图标表示坐标位置是以所选对象的左上角为基准还是以中心为基本。当前左上角方块呈黑色显示,表示坐标位置以对象左上角为基准,如果中心方块呈黑色显示,表示坐标位置以对象中心为基准。

通过更改_x和_y属性可以在影片播放时改变影片剪辑的位置。如可以为影片剪辑编写如下的事件处理函数:

onClipEvent (enterFrame) {

_x += 5;

_y += 5;

}

该事件处理函数使影片剪辑在每次enterFrame事件中向右和向下移动5像素的位置。

2 鼠标位置

你不但可以获得影片中影片剪辑的坐标位置,还可以获得鼠标位置,即鼠标光标在影片中的坐标位置。

表示鼠标光标的坐标属性的关键字是_xmouse和_ymouse,其中,_xmouse代表光标的水平坐标位置,_ymouse代表光标的垂直坐标位置。

需要说明的是,如果这两个关键字用在主时间轴中,则它们表示鼠标光标相对于主场景的坐标位置;如果这两个关键字用在影片剪辑中,则它们表示鼠标光标相对于该影片剪辑的坐标位置。_xmouse和_ymouse属性都是从对象的坐标原点开始计算的,即在主时间轴中代表光标与左上角之间的距离;在影片剪辑中代表光标与影片剪辑中心之间的距离。

多数情况下,你需要用到鼠标光标在主场景中的位置,所以可以使用_root._xmouse和_root._ymouse表示。

你可以使用下面的代码让影片剪辑保持与鼠标位置相同的坐标值:

onClipEvent (enterFrame) {

_x = _root._xmouse;

_y = _root._ymouse;

}

Flash不能获得超出影片播放边界的鼠标位置。这里的边界并不是指影片中设置的场景大小。如将场景大小设置为550×400,在正常播放时能获得的鼠标位置即在(0,0)~(550,400)之间;如果缩放播放窗口,将视当前播放窗口的大小而定;如果进行全屏播放,则与显示器的像素尺寸有关。

3 旋转方向

影片剪辑的另一个属性是_rotation._rotation属性代表影片剪辑的旋转方向,它是一个角度值,介于-180°~180°之间,可以是整数和浮点数。_rotation的值始终保持在-180°~180°之间,如果将它的值设置在这个范围之外,系统会自动将其转换为这个范围之间的值。例如,将_rotation的值设置为181°,系统会将它转换为-179°;将_rotation的值设置为-181°,系统会将它转换为179°。

如使用下面的语句实现影片剪辑的连续转动:

onClipEvent (enterFrame) {

_rotation += 10;

}

不用担心_rotation会超出它的范围,系统会自动将它的值转换到-180°~180°之间,并不会影响到影片剪辑转动的连贯性。

4 可见性

影片剪辑的另一个属性是_visible,即可见性。_visible属性使用布尔值,即要么为true(1),要么为false(0)。为true表示影片剪辑可见,即显示影片剪辑;为false表示影片剪辑不可见,隐藏影片剪辑。

例如要隐藏影片剪辑myMC:

myMC._visible = false;

5 透明度

_alpha(透明度)是区别于_visible的另一个属性,_alpha决定了影片剪辑的透明程度,它的范围在0~100之间,0代表完全透明,100表示不透明。

例如要将影片剪辑myMC的透明度设为50%:

myMC._alpha = 50;

_alpha属性代表了第4种颜色通道,即所谓的alpha通道。前3种颜色通道分别为red(红)、green(绿)、blue(蓝),也就是我们说的三原色通道,通常也简称R、G、B通道。前3种颜色通道决定像素的颜色成份,alpha通道决定像素的透明程度。在计算机中,每种颜色通道都用8 bit(位)来存储,所以如果一幅图像是32位的,它就有所有这4个通道;如果一幅图像是24位的,则它就只有R、G、B这3个通道。

也可以在脚本中设置按钮的_alpha属性。特别指出,将按钮的_alpha属性设置为0,虽然按钮不可见,但是它的热区同样存在,仍然可以对它进行单击等操作;如果要将按钮变为不可用,可以将其_visible属性设置为false。

6 缩放属性

影片剪辑的缩放属性包括横向缩放_xscale和纵向缩放_yscale。

_xscale和_yscale的值代表了相对于库中原影片剪辑的横向尺寸width和纵向尺寸height的百分比,而与场景中影片剪辑实例的尺寸无关。如库中影片剪辑元件的横向宽度为150,在场景中将它的实例宽度调整为10,在脚本中将_xscale

设置为50,则它在影片播放时显示的横向宽度将是150的50%,即75,而不是50像素或10的50%。

当_xscale和_yscale是0~100之间的数时,缩小原影片剪辑;当_xscale和_yscale是大于100的数时,放大原影片剪辑;当_xscale或_yscale为负时,将在缩放的基础上水平或垂直翻转原影片剪辑。

本例文件包含了一个矩形的影片剪辑和一幅图片,并将矩形所在图层作为遮罩层,如图6-4所示。

在矩形影片剪辑的动作面板中添加如下ActionScript:

onClipEvent (load) {

xs = _width;

ys = _height;

}

onClipEvent (enterFrame) {

_xscale = 100*(_root._xmouse-_x)/(xs/2);

_yscale = 100*(_root._ymouse-_y)/(ys/2);

}

在load事件中,用变量xs和ys取得影片剪辑初始状态下的宽度和高度值。在enterFrame事件中,计算鼠标位置与矩形影片剪辑中心的距离,算出它与矩形宽度和高度值的比值,然后作为_xscale和_yscale的值。该动画实现移动鼠标位置以改变遮罩效果。

7 尺寸属性

上面例子中我们用到了影片剪辑的另两个属性:_width和_height。与_xscale和_yscale属性不同,_width和_height代表影片剪辑的绝对宽度和高度,而不是相对比例。

同样可以使用_width和_height调整影片剪辑的尺寸大小,如上例中的ActionScript也可写成如下所示:

onClipEvent (enterFrame) {

_width = (_root._xmouse-_x)*2;

_height = (_root._ymouse-_y)*2;

}

是一个内置函数,用以计算一个数或表达式的绝对值。因为与缩放属性不同,_width和_height的值不能为负,所以这时使用绝对值函数始终给出一个不为负的值。

此处用更简洁的脚本实现了与上例相同的效果。

动画包含一支球杆影片剪辑stick,一个母球影片剪辑ball。在屏幕中移动鼠标,球杆会跟随鼠标转动,这是利用鼠标位置控制球杆的_rotation属性。球杆的影片剪辑中添加了一个隐性按钮(只有最后1帧作为热区,前面3帧都有为空,所以是不可见的),当单击球杆时,控制球杆影片剪辑向后播放,作回拉动作,再出杆击球。当球杆前端回到球的轮廓位置时,用球杆影片剪辑控制母球影片剪辑,将母球击出,然后将其自身的_visible属性设置为false,隐藏球杆。通过调整母球的_x和_y属性,实现母球的滚动、反弹等动作。在母球滚动时,分析母球位置以判断母球是否落袋,如果母球落袋,则使用trace语句给出提示“bad”,将母球重新置于初始位置。当母球停止滚动时,将球杆的_visible属性重新设置为true,并将球杆的位置设置为与母球相同,等待下一次击球。

球杆stick影片剪辑元件:

(1)在stick影片剪辑元件第1帧的帧动作面板中添加如下语句:

stop();

(2)在第2、10、12帧中添加动作,使球杆作回拉——出杆运动。第12帧时的球杆前端应与中心保持相当于母球半径长度即7.5像素的距离,在此帧时将母球击出。

(3)在第12帧的动作面板中添加如下ActionScript:

_ball.v = 20;

_ = _._rotation;

上面的语句为motherball实例传送两个参数值v和dir,v代表了母球的运动速度,dir代表了母球的运动方向,它的方向与球杆的旋转方向相同。

(4)在第13~20帧添加过渡,使球杆击球后在场景中保留一段时间。

(5)在第20帧的动作面板中添加如下ActionScript:

_visible = false;

该语句将球杆自身隐藏。

(6)将第1帧中的球杆转换成按钮,选中该按钮,在动作面板中添加如下ActionScript:

on (release) {

play();

}

单击该钮,球杆往后播放,作击球动作。

球杆影片剪辑实例:

在主场景中将球杆和母球放在左边,将它们的中心对齐。为球杆影片剪辑添加如下ActionScript:

onClipEvent (load) {

_x = _ball._x;

_y = _ball._y;

}

onClipEvent (mouseMove) {

xsm = _root._xmouse-_x;

ysm = _root._ymouse-_y;

if (xsm<0) {

_rotation = (ysm/xsm)*(180/);

} else {

_rotation = (ysm/xsm)*(180/)+180;

}

}

是Flash的内置函数,用它求一个数或表达式的反正切值。是Flash的内置常数,代表圆周率。使用计算出的反正切值的单位是弧度,而_rotation属性的单位是角度,所以要将其乘以(180/)以实现弧度到角度的转换。

在球杆影片剪辑的mouseMove事件中,根据鼠标位置调整_rotation属性的值,使影片剪辑跟随鼠标转动,这也是鼠标跟随动画中的一种。

母球影片剪辑实例:

在母球影片剪辑实例的动作面板中添加如下ActionScript:

onClipEvent (load) {

v = 0; //初速度

dir = ""; //运动方向

vx = 0; //x方向分速度

vy = 0; //y方向分速度

slow = 0; //加速度

x0 = _x; //初始x位置

y0 = _y; //初始y位置

}

onClipEvent (enterFrame) {

//母球运动中

if ((dir != "") && (slow<100)) {

//母球落袋

if (((_x<60) && (_y<85)) || ((_x>440) && (_y<85)) || ((_x<60) && (_y>265))

|| ((_x>440) && (_y>265))) {

_visible = false;

trace("Bad!");

dir = "";

v = 0;

vx = 0;

vy = 0;

slow = 0;

_x = x0;

_y = y0;

_visible = true;

//在母球位置显示球杆

_._visible = true;

_dStop(1);

_._x = x0;

_._y = y0;

}

//撞击球桌左边界

if (_x<60) {

_x = 60;

dir = -(180+dir);

}

//撞击球桌右边界

if (_x>440) {

_x = 440;

dir = 180-dir;

}

//撞击球桌上边界

if (_y<85) {

_y = 85;

dir = -dir;

}

//撞击球桌下边界

if (_y>265) {

_y = 265;

dir = -dir;

}

//调整母球位置和速度

v0 = v*(100-slow)/100;

vx = v0*((dir)/(180/));

vy = v0*((dir)/(180/));

_x += vx;

_y += vy;

slow++;

}

//母球减速完毕

if (slow == 100) {

//在母球位置显示球杆

_._x = _ball._x;

_._y = _ball._y;

_._visible = true;

//重置变量

dir = "";

v = 0;

vx = 0;

vy = 0;

slow = 0;

}

}