還記得Flash 4的時候Action只是協(xié)助Flash把動畫做得更好,或增加一些普通的外部命令、簡單的流程控制;到了Flash 5已經(jīng)可以作為一個較成熟的Script運行環(huán)境了,不過很多人還是當(dāng)它為矢量的Photoshop來用;經(jīng)過了不算太長的1年多,可愛的Flash MX終于出現(xiàn)了,她要告訴我們的是——你只需要鍵盤就足夠了。
從幾何圖形學(xué)來講,所有的圖形都可以用三角形表示,這個定理也適用于我們通常所看到的2D圖片和3D圖形。很多次,有人羨慕的說,阿,我要是可以用代碼完成你的作品該多好啊?Ok,我們給你Flash MX,只要你不嫌累并且打字快,你也可以做到。確實,這是一個矛盾的時間效率話題,也許不同的人會有不同的解釋,不過作為Flash MX的教程,我可以主觀地先告訴你Flash MX可以做到怎樣的程度,然后我們再討論這個矛盾。
Flash MX的畫線功能更類似于小的時候?qū)W習(xí)用的LOGO語言(就是那個小烏龜)。Macromedia公司把這些功能很好的嵌入了MovieClip對象中,并且每條語句都十分有用,如果善加利用,甚至可以用這些來寫出3D的引擎,相信在未來的幾個月內(nèi)會有這樣的東西出現(xiàn)。好了,先不管未來,我們先看看她的繪畫流程:
設(shè)置起點-〉從這個起點繪制到其他的點線條,并設(shè)置那個點為新的起點-〉填充顏色。
這個流程也基本是所有類似繪圖引擎的過程,我們先用幾行簡單而且十分有用的代碼來形象的說明這個流程(注意,今天不可以用手畫,偷懶對自己可沒好處……這句話今天相反)
新建一個文件,在主場景*幀加入代碼:
createEmptyMovieClip("drawobj",1);//這條語句在*天已經(jīng)出現(xiàn),就是要動態(tài)建立一個MovieClip。
drawobj.onMouseDown=function(){this.lineto(_root._xmouse,_root._ymouse)};
drawobj.linestyle(.1, 0x111111, 100);
效果是不是很酷?三行代碼基本上跟Windows畫板差不多啦。我們主要是用了lineTo這個函數(shù),它的主要功能是從當(dāng)前起點繪制一條直線到目標(biāo)點,當(dāng)然,你只要給目標(biāo)點的x和y坐標(biāo)即可;但你知道這個還不行,需要給你要畫的線條一種樣式,這就是linestyle,我們在這里畫的就是0.1厚度,灰黑色的,Alpha為100(不透明)的線。(圖1)
(圖1,……不是畫魔畫的L)
Ok,抓筆的人已經(jīng)松開了吧。我們要在lineto的基礎(chǔ)上改進一下,加入如下代碼:
createEmptyMovieClip("drawobj", 1);
Movieclip.prototype.makeBox = function(x, y, l) {
this.lineto(x, y+l);
this.lineto(x+l, y+l);
this.lineto(x+l, y);
this.lineto(x, y);
}; //init
with (drawobj) {
moveto(100,100);
beginfill(0x333333, 100);
linestyle(.1, 0x111111, 100);
makeBox(100,100,100);
endfill();
}
我們定義的makeBox如其名,就是畫正方形的,它在我們的初始化部分會用到,l參數(shù)是邊長。當(dāng)程序初始化的時候,我們對drawobj進行操作,首先用moveto來改變它的位置,接著我們會用到fill;它包括兩部分,一個是普通的beginfill,是設(shè)置填充的參數(shù)起點,當(dāng)我們用makeBox畫好了正方形后,必須要用到endfill才可以更新當(dāng)前的fill,否則什么beginfill也沒什么意義(雖然我不加也照樣更新)。(圖2)
(圖2)
再接再厲,我們再結(jié)合另一個方法來看看程序作出來的圖形的魅力。加入代碼: createEmptyMovieClip("drawobj", 1);
drawobj.linestyle(.1, 0x111111, 100);
for (var i=0; i<=50; i+=.1) {
with (drawobj) {
moveto(random(300),random(300));
beginfill(random(1048576),random(100));
curveto(i*random(10),i*random(10),i*random(10),i*random(10));
endfill();
}
}
這里我們先拋棄所謂的程序執(zhí)行效率,用感性的大腦來寫程序。憑空想象可能發(fā)生的事情,如果不知道的話,就隨便寫幾個random,然后動態(tài)改變顏色和Alpha,*用curveto方法來畫曲線。值得注意的是curveto的后兩個參數(shù)x軸曲線偏移和y軸曲線偏移,不要做的太大,否則會更慢……,程序?qū)懲旰髨?zhí)行一下,n秒鐘后出現(xiàn)了一幅圖畫,看起來還有點味道(圖3)
(圖3,我不知道是什么,我想畢加索也不知道)
看來,藝術(shù)的意義永遠無法解釋,但我們的程序還得繼續(xù)往下寫。上面說的Fill方法的*種是普通的beginFill,只可以填充固定的顏色;而另一種就比較好用了,叫做beginGradientFill,用途是填充過渡色。還是先來動手再說是怎么回事,加代碼: createEmptyMovieClip("drawobj", 1);
drawobj.linestyle(.1, 0x111111, 100);
for (var i=0; i<=100; i++) {
with (drawobj) {
cx=random(200);
cy=random(200);
makeBox(cx,cy,random(100));
drawWay=random(2) ===1 ? "linear" : "radial";
colorRange = [0x111111, 0xeeeeee];
alphaRange = [random(100), random(100)];
ra = [0, random(255)];
colorChart = {a:random(100), b:0, c:0, d:random(100), e:0, f:random(100), g:random(100), h:random(100), i:1};
beginGradientFill(drawway, colorRange, alphaRange, ra, colorChart);
}
}
這里我們分別使用begineGradientFill的兩種填充方式:linear線性填充和radial環(huán)行填充來演示了一些正方形組合在一起的樣子。這種填充方式需要的數(shù)據(jù)比較多,而且都為數(shù)組形式,其格式是*的:beginGradientFill(方式,顏色范圍,Alpha范圍,過渡范圍,過渡參數(shù)),缺一不可;但是過渡參數(shù)的形勢可以有兩種,一種是以3*3矩陣表示,內(nèi)容為[a,b,c,d,e,f,g,h,i],分別表示填充的寬,x軸起點,y軸起點,明度,x軸偏移色,y軸偏移色,高,填充角度等填充參數(shù);而另一種比較直觀,是以[x軸起點;y軸起點;寬;高;填充角度]組成的數(shù)組,我比較喜歡這種方式,方便而且速度快一些。我們隨機的放入一些數(shù)據(jù)來看看能形成什么樣子,不過在這個過程中,我意外的發(fā)現(xiàn)如果我們先用makeBox,再做Fill,那么將不會用到endfill()來結(jié)束填充(這個endfill總感覺沒什么用途,或者說沒有它應(yīng)該有的功能)。運行一下,又經(jīng)過幾十秒后,一幅很酷的類似某有名設(shè)計師的畫面出現(xiàn)了……(圖4)
(圖4,真的眼熟……)
*,如果你不喜歡這個樣子,你可以用drawobj.clear()來清空你畫的這些……
程序化的Mask蒙版
Flash MX現(xiàn)在已經(jīng)可以在程序中直接定義兩個Mask的主從關(guān)系,讓我們從一個例子來看看:(代碼)
Movieclip.prototype.makeBox = function(x, y, l) {
this.lineto(x, y+l);
this.lineto(x+l, y+l);
this.lineto(x+l, y);
this.lineto(x, y);
};
createEmptyMovieClip("drager",2);
drager.linestyle(.1, 0x111111, 100);
drager.beginfill(0x333333, 100);
drager.makeBox(0,0,30);
drager.endfill();
createEmptyMovieClip("jpgObj",1);
createEmptyMovieClip("loader",3);
loader.onenterframe=function(){
if(_root.jpgObj._width<>0){
_root.jpgObj.setMask
(_root.drager);removeMovieclip(this)
}
};
jpgObj.loadMovie("boy.jpg");
drager.startDrag(true);
這個例子我們結(jié)合這幾天所學(xué)的一些東西,而且還用到了那個小男孩。程序開始的時候會畫出一個灰色的正方形,當(dāng)然作為Mask的MovieClip顏色是無所謂的,接著我們再創(chuàng)建一個MovieClip,作為被Mask的對象,當(dāng)然到這里理論上我們可以直接用命令來控制Mask,但是,我們要考慮圖片是否被讀取的這個因素。而且,還是理論上我們可以用ondata這個事件來獲取,但是F6播放器做的好象有問題……MovieClip的ondata被錯誤的傳遞給了_root,而且還不是正確的時候傳遞的。那我們沒辦法,只好再增加一個loader MovieClip作為判斷是否讀取得條件,當(dāng)然,滿足后需要自己釋放自己所占有的內(nèi)存,并且用setMask來遮蓋我們所讀取的圖片;*,把方塊綁在鼠標(biāo)上就完成了,整個流程看似基本上不會發(fā)生什么錯誤了……(圖5)
(圖5)
源文件:
注:
FlashMX的程序雖然基本上都可以寫入*幀,但是如果考慮時間效率的話,還是分批處理為妙,例如把初始化和最常用的Action先處理,其他的可以放入.as或者別的幀。