3.3 虚幻特效(6)
3.3.2 天堂之云
云彩效果在Flash中也是非常麻烦、非常难制作的,这个在Flash 5时代很棘手的问题在Flash MX中可以通过编程来实现了。因为在Flash MX中有一个非常强大的渐变填充功能,让我们先看看这个渐变填充功能的说明吧(参考了fictiony自在幻想在闪客帝国论坛的有关帖子):
函数格式:
MovieClip.beginGradientFill (fillType, colors, alphas, ratios, matrix)
参数:
fillType:填充类型,可以为“linear”(线性填充)或者“radial”(辐射填充)两种。
colors:一个RGB颜色数值的数组,范围为0x000000~0xffffff,用于指定渐变填充里所用到的组成颜色,这个数组有几项就说明填充有几种颜色。
alphas:填充中每一个组成颜色的透明度数值的数组,其范围是0~100,如果其值小于0就默认为0,如果大于100就默认为100。
ratios:一个颜色分配定量数组,范围为0~255,用于指定每一个组成颜色所在的位置,最左端为0,最右端为255,中间按比例折算,它与Color Mixer面板中渐变色的组成有着相对应的地方。
在这里,colors,alphas,ratios都是一维数组,且数组的length值必须相等。
matrix:一个变形矩阵,它有两种形式。
第一种为标准3×3的二次变换矩阵,形式为:
a, b, c
d, e, f
g, h, i
具体写的时候就写成{a:#, b:#, c:#, d:#, e:#, f:#, g:#, h:#, i:#},其中#表示具体的数值。这个矩阵每个元素的具体含义在计算机图形学中有,后面会具体解释。
第二种为缩放旋转变换矩阵,形式为:
x, y (中心点位置)
w, h (x、y轴方向的缩放比例,原始大小为1像素)
具体写的时候就写成{matrixType:"box", x:#, y:#, w:#, h:#, r:#} r (旋转的角度,弧度单位,由于辐射填充本来就无角度,故这个参数只对线性填充有效)。这个矩阵具体给出了缩放的比例和旋转的角度,控制起来更直观些,但效率不高。Flash内部处理时会先转化成第一种的矩阵模式,以提高运算效率。在实际的填充过程中,如果w或h的值比实际区域要大,则先根据w或h值的区域填充然后再按实际的区域进行裁剪。
下面再扩充一下matrix这个参数的具体含义。
学过计算机图形学的人都知道二次变换矩阵的形式如下:
a, b, 0
d, e, 0
g, h, 1
一个坐标点(x0, y0),在经过二次变换(也就是缩放+旋转+移动)后,其坐标假设变成(x1, y1),那么x1、y1的矩阵运算公式就是:
[x1, y1, 1] = [x0, y0, 1][[a, b, 0],[d, e, 0], [g, h, 1]]T
等价于:
[x1, y1, 1] = [x0×a+y0×d+1×g, x0×b+y0×e×1×h, x0×0+y0×0+1×1] = [ax0+dy0+g, bx0+ey0+h, 1]
matrix的第一种形式就是这个标准二次变换的矩阵,其中c,f,i三个参数其实可以随便设置,因为Flash内部会自动取0,0,1的值。 如果把二次变换的过程拆开,也就是把缩放、旋转和移动一步步进行,那么就成了第二种形式。这里假设x轴缩放比例为w,y轴缩放比例为h,旋转度数(弧度)为r,移动的相对位置为(x,y)。那么这里的参数就和matrix第二种形式一一对应了。我们来看具体过程,假定先旋转,后缩放,最后移动。
首先旋转,那么就有:
[x1, y1] = [x0cos(r) + y0sin(r), x0sin(r) – y0cos(r)]
之后缩放,那么就有:
[x2, y2] = [x1w, y1h] = [wx0cos(r) + wy0sin(r), hx0sin(r) – hy0cos(r)]
之后移动,那么就有:
[x3, y3] = [x2+x, y2+y] = [wx0cos(r) + wy0sin(r) +x, hx0sin(r) – hy0cos(r) +y]
当我们把这两种模式所得到的结果进行对比就可以发现:
[ax0+dy0+g, bx0+ey0+h] = [wx0cos(r) + wy0sin(r) +x, hx0sin(r) – hy0cos(r) +y]
也就是有:
a = wcos(r)
b = hsin(r)
d = wsin(r)
e = –hcos(r)
g = x
h = y
但事实上,二次变换并没有限定缩放、旋转和移动的次数。也就是说,我们可以反复进行这些子变换,而最终得到一个对应关系。数学上已经证明,这样的子变换不论进行多少次,最后都能把坐标写成[ax0+dy0+g, bx0+ey0+h]的形式。所以第一种形式的matrix写法所能描述的范围要比第二种大。对于第二种形式,Flash内部的处理方式是和前面假定的方式一样:先旋转、后缩放、最后移动。这样我们就可以看到,对于辐射渐变来说,先旋转毫无意义,这也是为什么第二种形式无法设置辐射渐变的旋转角度的原因所在。
看看“自在幻想”给出的一个例子,用来显示两种形式的matrix之间的对比,可以看到,它们的效果(在某种程度上)是相同的:
http://no-e.net/friend/chinavane/fictiony/gradientfill.fla
http://no-e.net/friend/chinavane/fictiony/gradientfill.swf
(注:h加了200是为了让它的中心下移到和上面相对应的地方,不然两个色块的填充就重合了,看不出对照效果。)
好了,讲了这么多复杂的理论,是不是有点头昏呢?其实如果读者觉得这些关于计算机图形学理论太过于复杂,记不住就算了,就采用第二种方法吧,这种方法比较容易理解与记忆。下面看一个实例:
_quality = "LOW";
begin_x = 70;
begin_y = 250;
y_move_speed = 4;
//先产生一个空白的填充效果
createEmptyMovieClip("dongua_sparkle", 100);
with (_root.dongua_sparkle) {
beginGradientFill("radial", [0xffffff, 0xffffff], [100, 0], [0, 255], {matrixType:"box", x:0, y:0, w:20, h:20, r:0});
//顺时针画个圆,然后用前面的定义的白色渐变色填充
moveTo(10, 0);
curveTo(20, 0, 20, 10);
curveTo(20, 20, 10, 20);
curveTo(0, 20, 0, 10);
curveTo(0, 0, 10, 0);
endFill();
}
//这里的tabX与tabY分别代表一个圆的圆心位置,共有20个圆
arrays = {tabX:[], tabY:[250, 210, 440, 400, 350, 220, 350, 260, 340, 400, 250, 210, 440, 400, 350, 220, 350, 260, 340, 400]};
dongua_sparkle._visible = false;
_root.onEnterFrame = function() {
for (i=0; i<20; i++) {
name = "dongua_sparkle_"+i;
duplicateMovieClip(dongua_sparkle, name, i);
_root[name]._x = arrays.tabX[i];
_root[name]._y = arrays.tabY[i];
_root[name]._xscale = 4*arrays.tabX[i];
_root[name]._yscale = 4*arrays.tabY[i];
_root[name]._alpha = arrays.tabY[i]/6;
//让云彩往上飘,移动方式以cos函数为基准,每次移动距离很小
arrays.tabY[i]=arrays.tabY[i]-y_move_speed/ 2*Math.cos(angle-i)-y_move_speed;
//如果云彩的中心小于5时就重新从下面开始
if (arrays.tabY[i]<5) {
arrays.tabY[i] = begin_y;
}
//云彩的x坐标变化值是以sin函数为基准
arrays.tabX[i] = begin_x+(30*Math.sin(angle-i));
//调整角度
angle = angle+0.002;
}
};
这个特效的核心就是通过产生20个圆,用白色渐变填充,然后控制它的大小、宽度,再让它从下向上飘动,同时修改它的大小、宽度与透明度,当它到最顶端后,透明度也基本降到了最低,然后又重新从下面开始。用来控制它的x坐标的是sin函数,而sin函数的取值范畴是[–1,1],arrays.tabX[i]=…程序中用30来乘就扩大了x坐标的波动范围,可以在[begin_x–30, begin_x+30]内波动。用来控制y坐标的是cos函数,arrays.tabY[i]=…这一句实际上是保证渐变的圆每次上移的距离在[0.5*y_move_speed,1.5*y_move_speed]之间,从而保证了上移是连续的!而最后一句中angle每次调整的角度非常之小,只有0.002,这就是为了让sin函数和cos函数求出的值与上次变化非常小,肉眼看上去每一次变化都很细小,从而达到预期的效果。见图3-14与图3-15只是连续变化效果的两个画面,其实效果是极具动感的。
|