——概念描述
這個項目的概念是使來到我網站的人有機會用FlashMX設計一本虛擬書,就象一本真正的書那樣,不過它是擺在你的電腦案頭上的。你可以一頁一頁地閱讀。
注意,這個課程是面向那些對ActionScript有所瞭解以及知道如何在FlashMX中編碼的人。如果你只知道如何建立一個球並讓它在案頭上滾動,那麼請過幾個月再來吧。
只是開玩笑啦。基本上在這個課程裡只有很少的技術。在這個教程中的所有函數是經常使用的。編碼非常容易,你需要知道的只是一些基本的三角知識,比如sine(正弦)、cosec(餘弦)、hypotenuse(直角三角形的斜邊)。這些對於這個教程來說就足夠了。所以,放輕鬆,好好享受吧。
第一部分
——基本計算函數
在這個根指令碼(root script)裡,我們有兩個基本計算函數。你可以把它們直接拷貝到你的舞台(stage)上,因為我們將會一遍遍用到它們。一個是getDist,另一個是getAngle。它們對你來說很簡單,是吧?老實說,我都沒興趣解釋這樣的東西,這些是高中數學課上該學的。
第一個函數是獲得兩點之間的距離。我們需要知道這兩點之間的座標。
//(得到兩點之間的距離)function getDist(px1, py1, px2, py2){ x = px2 - px1 y = py2 - py1; hyp = Math.sqrt(Math.pow(x,2) + Math.pow(y,2)); return hyp;}
好了,現在你進展已經不錯。我們可以試一下更痛點的。——怎麼獲得兩點之間的角度。
//(得到兩點之間的角度)function getAngle(px1, py1, px2, py2){ x = px2 - px1; y = py2 - py1; hyp = Math.sqrt(Math.pow(x,2) + Math.pow(y,2)); cos = x / hyp; rad = Math.acos(cos); //(如果你看不懂,就去問你的數學老師) deg = 180/(Math.PI / rad); //(是的,我們通過cos得到了一個角度“rad”,不過是以弧度為單位的) //(因此,我們需要再進一步把它轉換成我們所需要的標準的角度) if(y <0){deg = -deg;} else if((y == 0) && (x <0)){deg = 180;}return deg;}
我不需要做更多解釋了吧?
第二部分
——舞台上基本的Movie Clips
在庫(library)中建立4個方塊符號(symbol)。它們是你書中的不同的頁面。如果你喜歡,你可以根據需要重新設計。我只需要提醒你一件事,就是,把參考點放在每個symbol的左下角,我們需要用它們來找到頁面的位置。
在這個示範例子裡,假定我們的書只有4頁。如果你想讓你的書頁數更多,那就請自己加一些新的check situation函數。要確保頁面的大小與書本相符。
把它們拖到你的舞台上,確保它們在不同的層面。
按照這個順序:第4頁,第1頁,第2頁,第3頁。
第3頁應該在最上面一層。
確保將這些movie clip如所示放置。
第3頁的具體位置沒什麼要緊,因為我們將會把它做動態調整。
2、建立一個符號(symbol)圓,並切割下來(cut)。我們需要在移動滑鼠的時候用它來檢查不同的位置。
3、建立一個包含一個點的symbol,你可以用任何風格的點,這取決於你把“點”這個symbol在舞台上放5次,分別命名為D0,D1,D2,D3和D4。
我需要提醒你的是,不要在movie clip Page1和Page4的地區外放置任何movie clip。
4、我們還會需要一些別的符號(symbol),比如陰影或別的什麼,我們可以遲一點再建立它們,別擔心。
現在再數一次,你庫(library)裡的符號(symbol)有:
s_circle, s_dot, s_page1, s_page2, s_page3, s_page4
你舞台(stage)上的符號(symbol)有:
checkcircle, D0, D1, D2, D3, D4, page1, page2, page3, page4
把舞台(stage)上所有的movie clip選中,把它們轉換(convert)為一個符號(symbol) s_stage。
把s_stage拖到舞台上,把它命名為movie clip“Stage”。
確保movie clip D0位於movie clip“Stage”的中心。
確保movie clip “Stage”的大小是Page 1 加 Page 4。
這就是為什麼當你在轉換符號s_stage的時候不要在地區外面放置任何movie clip的原因。
基本上,建立movie clip D0到D4 的目的是為了清楚找到參考點。當我們完成這個教程的時候,你可以把這些movie clip的透明度設定為0。我這裡就是這麼做的。
我們可以在下面的課程中開始編碼了。
第三部分
——初始化
如所示初始化所有變數。
//(設定書的寬和高)stageW = _root.stage._width;stageH = _root.stage._height;//(設定參考點的位置)pax=_root.stage.d0._x - stageW/2;pay=_root.stage.d0._y - stageH/2;pbx=_root.stage.d0._x - stageW/2;pby=_root.stage.d0._y + stageH/2;pcx=_root.stage.d0._x;pcy=_root.stage.d0._y - stageH/2;pdx=_root.stage.d0._x;pdy=_root.stage.d0._y + stageH/2;pex=_root.stage.d0._x + stageW/2;pey=_root.stage.d0._y - stageH/2;pfx=_root.stage.d0._x + stageW/2;pfy=_root.stage.d0._y + stageH/2;_root.stage.page3._alpha = 0;//(我們需要在開始的時候顯示movie clip Page2,所以先隱藏Page 3)
把這部分代碼放入你的第一個根指令碼(root frame script)。
——怎麼找到第一個點?
第一個點,D1,是你滑鼠的位置。(說實在話,在D1的位置上有幾種情況。假設你的滑鼠離開了movie clip圓,會發生什嗎?你可以遲一些時候再完成這部分。我已經做好了。這是留給你的作業。)
在給D1的位置賦值之前,我們首先需要一個主函數。
//(主函數)function startSlip(){
getD1(); //(這個函數是我們要在這一課中討論的)getD234();DrewMask(); //(我們將在以後添加這兩個函數)}
現在你可以檢查如何設定D1了。
//(得到第一點,D1的位置)function getD1(){ if (_root.stage.checkcircle.hittest(_xmouse, _ymouse, true)) { _root.stage.d1._x = _root.stage._xmouse; _root.stage.d1._y = _root.stage._ymouse; }else{ //(自己完成這部分。基本上,我還要用三個函數來設定 D1的位置) }}
提示:你的滑鼠要去四個地區,在每個地區裡,D1的位置是不同的。在這個例子裡,我們只討論地區A。我會把所有的代碼放在最終檔案裡,你如果感興趣的話,可以稍後查看。
因為要按住滑鼠拖動頁面,你需要移動的第一個點是在頁面右下角的點。
很好,我們還有三個點要做,耐心一點。
第四部分
——得到所有其他三個點:
同上面一樣,你有幾種情況要考慮。
第一種情況比較簡單。第3點位於邊EF上。在這種情況下,點D4與點D3位於同一位置。
另一種情況比較難一點。點D3位於邊CE上。你需要計算D3和D4。
或者:
這裡,我們需要一些三角函數來獲得所有的數值。嗨,一定有更有效方式來編碼,我真是沒興趣再做一遍。:(
我只需要提醒你一件事:
Flash的座標系開始於左上方,逐漸向下擴充到右邊。
對於一個數學家來說,求得所有的點很可能只需要幾分鐘,但是我卻花了整整一個上午。如果你想做,你可以自己做,或者只需拷貝這些代碼。
//(用D1和F來找到其他的點)function getD234(){ len = _root._root.getDist(pfx, pfy, _root.stage.d1._x, _root.stage.d1._y); len1 = len/2; len2 = (pfx - _root.stage.d1._x)/2; _root.stage.d2._x = pfx - len1*len1/len2; _root.stage.d2._y = pfy; len2 = (pfy - _root.stage.d1._y)/2; len3 = len1*len1/len2; _root.stage.d3._x = pfx; _root.stage.d3._y = pfy - len3; //(檢查D4是否和D3在同一個位置) if (_root.stage.d3._y < pey){ ptx = pex - (pfx - _root.stage.d2._x)*(pey - _root.stage.d3._y)/len3;pty = pey;len = _root.getDist(_root.stage.d3._x, _root.stage.d3._y, ptx, pty);len1 = (pex - ptx)*(pey - _root.stage.d3._y)/len;len2 = len1*len1/(pex - ptx);_root.stage.d4._x = pex - len2*2;len2 = len1*len1/(pey - _root.stage.d3._y);_root.stage.d4._y = pey - len2*2;_root.stage.d3._x = ptx;_root.stage.d3._y = pty; }else{ _root.stage.d4._x = _root.stage.d3._x;_root.stage.d4._y = _root.stage.d3._y; }}
哇,現在我們快完成了,繼續!
第五部分:
——繪製mask shape
你只需要知道兩個特別的點。一個點建立一個空的movie clip,並在其中繪製一些東西。另一個點用另一個動畫來遮住一個movie clip。
好了,讓我們來編碼。
//(建立遮罩movie clip)function drawMask(){ _root.stage.createEmptyMovieClip ("triangle", 1); with (_root.stage.triangle) { colors = [ 0xEFEFEF, 0xFFFFFF ];alphas = [ 100, 100 ];ratios = [ 0, 0xFF ];matrix = { a:200, b:0, c:0, d:0, e:200, f:0, g:200, h:200, i:1};beginGradientFill( "linear", colors, alphas, ratios, matrix );moveTo (_root.stage.d1._x, _root.stage.d1._y);lineTo (_root.stage.d2._x, _root.stage.d2._y);lineTo (_root.stage.d3._x, _root.stage.d3._y);lineTo (_root.stage.d4._x, _root.stage.d4._y);lineTo (_root.stage.d1._x, _root.stage.d1._y);endFill();// (你能在Flash MX的協助或者參考中找到它們。我是從那裡拷貝過來的。) } setPage3(); //(我們需要在滑鼠移動時移動和旋轉movie clip Page3。這就是為什麼在這裡我們需要這個函數) _root.stage.page3.setMask(_root.stage.triangle);}
這是我們還需要知道的一個函數:setMask。
就個人而言,我認為這個setMask函數在使用時有些小bug。它不象其他函數那麼好用。
我要提醒你的另一件事是,在同一級指令碼裡你只能用setMask一次,意思就是,如果你想同時setMask movie clip Page2,你需要建立新的 mask movie clip,並在不同級的指令碼中setMask。很難理解嗎?好吧,在我的例子裡,我把下一個setMask放在movie clip Page2裡。
//(移動並旋轉movie clip Page3)function setPage3(){ _root.stage.page3._x = _root.stage.d1._x; _root.stage.page3._y = _root.stage.d1._y; angle = _root.getAngle(_root.stage.stage.d1._x,_root. stage.stage.d1._y, _root.stage.stage.d4._x, _root.stage.stage.d4._y); _root.stage.page3._rotation = angle + 90; //(為什麼這裡加了90度?我不知道。我只是發現加了這個之後數字才能很好地工作) _root.stage.page3._alpha = 100; //(記得我們把movie clip Page3的透明度設定為0了嗎? //現在我們需要把它變回去。因為movie clip Page2在Page3的下一層。) }
在這一課程中多加一條編碼。在movie clip “Stage”中
onClipEvent (enterFrame) { _root.startSlip();}
這一段代碼使Flash一直檢查滑鼠的位置。
第六部分:
——在Page2中繪製mask shape
在movie clip Page2裡建立一個新的名為Page2_content的movie clip。隨便你取什麼名都可以。
把下面的代碼加到新的movie clip Page2_content中。基本上,就象我們在上一個課程中討論的那樣,在同一級的script中,你只能使用setMask一次。這就是為什麼在movie clip Page2裡還需要再用一次的原因。這些代碼是為了顯示底部的movie clip Page4。
//(在movie clip Page2_content內部)onClipEvent (enterFrame) { _parent.createEmptyMovieClip ("triangle2", 1); _root.stage.page2.page2_content.setMask (_parent.triangle2); with (_parent.triangle2) { colors = [ 0xEFEFEF, 0xFFFFFF ];alphas = [ 0, 0 ];ratios = [ 0, 0xFF ];matrix = { a:200, b:0, c:0, d:0, e:200, f:0, g:200, h:200, i:1 };beginGradientFill( "linear", colors, alphas, ratios, matrix );moveTo (_root.pdx , _root.pdy - _root.stageH/2);lineTo (_root.stage.d2._x, _root.stage.d2._y - _root.stageH/2);lineTo (_root.stage.d3._x, _root.stage.d3._y - _root.stageH/2);lineTo (_root.pex, _root.pey - _root.stageH/2);lineTo (_root.pcx, _root.pcy - _root.stageH/2);lineTo (_root.pdx, _root.pdy - _root.stageH/2);endFill(); }}
檢查一下你現在進展如何了?很酷,對吧?
總結:
——你需要添加的其他東西
現在,我們已經完成得差不多了。但是,當然,我們還需要再做一點什麼,使它看起來象一本真正的書。
我們需要加一些陰影movie clip。我用png檔案來做透明效果。並且保證它隨著Page3一起移動旋轉。那些代碼有些相似。角度有些不同,因為現在旋轉軸不再是邊D1、D4,而是邊D2、D3。
另外:你要添加一個函數來檢測頁面如何回退和前進。在我最終的版本裡,我用了mouse release函數。
基本上,還會有比較難的一步,就是如何查驗第一頁和最後一頁。如果沒有那些,你就不能增加頁數。剩下的事情就作為你們自己的作業吧。:)
祝好運!