如何以平面偽裝3D空間?
filed in Flash on Sep.25, 2008 (4,794次檢視)
想信如果有研究開Flash的朋友,都應該聽說過papervision3d或away3d這一類的Flash 3D Engine。可是,要學習這些3D Engine的API,絕不是短時間可以學會的事。有時候,可能你想做的效果,並不是十分複雜,要用到papervision3d 又好像有些勞師動眾…
當Stanley還在玩Flash MX 2004 的時候,跟本還未有這些3D Engine存在。可是,Stanley卻有一些方法,利用簡單的數學”騙”用戶的眼睛,巧妙地利用平面偽裝3D空間呢!
3D空間感的元素
首先我們要了解構成3D空間感的元素是甚麼:
- 物件位置 (position)
- 物件大小 (scale)
- 物件的深度 (depth)
一個很簡單的關係就是: 物件位置愈近,物件就愈大,物件的深度也是最頂。相反,物件位置愈遠,物件就愈小,物件的深度也是最低層。因此,如果你能夠寫到一個數學關係,可以從一個3D 位置(x, y, z),計算出一個2D位置(x, y)、scale及depth,就不是已經完成了? 對! 就是這樣簡單啊!
例子
請先看Stanley 為大家準備好的例子:
>> 下載例子
酷嗎?是否很3D呢!?但它真是用2D偽裝出來的! 現在讓我為大家一一解構箇中玄機吧!
解構
其實整個程式的核心,就是以下的數式,我把這個數式放到一個class入面,方面大家使用:
public static function project(pos:Vector3D):Object {
var mx:Number = pos.x;
var my:Number = -pos.y; //in the 3D space, upwards means positive
var mz:Number = pos.z;
//calculate perspective
var pers:Number = FISH_EYE / (1 + mz);
//create return object
var returnObj:Object = {
x: mx * pers,
y: my * pers,
scale: pers * SCALE_FACTOR
}
return returnObj;
}
這個function你只要提供一個Vector3D的object,就可得出投射到平面上的位置及大小了。其中原理只是比例的計算,不深究了,但當中有兩個constant卻想談一談:
FISH_EYE:
如果你玩相機的,應該知道甚麼是焦距。焦距很短時(zoom out),相片可包含多些景物,相反在長焦距時,相片卻看到景物的一小部份。FISH_EYE這個值,說的就是焦距值了。
SCALE_FACTOR:
是用來控制計算出來的scale的,方便調較場景物年大小比例。
* Vector3D是我自己寫的一個class,有x,y,z三個屬性及一些向量的計算函數,如加、減、倍大、dot product、cross product等,對於3D programming是很有用的!
編程流程
要做到這個pseudo 3D 的效果,我會建議你跟著以下的步驟做:
- 準備movieclip
先做好想在3D空間出現的movieclip,並設定好屬性,方便之後動態地用actionscript加到場景上 - 設計場景
用actionscript吧movieclip動態地加到場景上,並自行定義變數去儲著物件的3D位置(x, y, z) - Projection
用我之前提供的函數,投射3D位置,得出2D位置及scale - 更新movieclip屬性
得出projection的結果,你可更新movieclip的屬性,如x, y, scale, alpha, depth 等等
注意事項
1. Depth
在AS 2.0中,movieclip的depth很容易設定的:
//number 可以是任何整數,最方便就是用z的值做depth value
mc.swapDepths([number]);
可是在AS 3.0中,已經沒有了swapDepths 這個函數了… 取而代之則是 setChildIndex 。可是,你不能隋便輸入任何整數的。例如你的containerMc中有20個logoMc,那麼以下的code就會有run time error了!
//error! 整數必須是由0 - 19,因為containerMc現在只有20個位
containerMc.setChildIndex(logoMc,30);
因此在AS 3.0中,要花心機寫排序的功能,把movieclip乖乖的編到0 – 19之中
2. 移動鏡頭
利用這個pseudo 3D的方法是沒有camera的,那如何可以做到移動camera的感覺呢? 答案是移動所有物件。比如你想把camera移近物件,其實相對地是可以看成物件移近camera。用這個relative motion的概念,就可以做出上面demo的效果了!
結語
在Flash中做3D效果,的確是有點難度,可是我卻很喜歡。因為3D programming,除了是編程外,還有美術,數學,物理以及程式優化等知識集於一身,必須相輔相成才可做到好的3D RIA。希望這個tutorial可以為大家提供一個低一點的門檻做3D程式吧!
>> 下載例子
>> 看其他教學

May 29th, 2009 on 2:16 pm
妳好啊,我是rix
對不起這樣唐突的留言..
那是因為看到妳的BLOG中有這個FLASH教學,這個效果好漂亮啊,所以我就DOWNLOAD了妳的例子和FLASH8試試看.. 結果有些檔案開不了..而開到的我又用不明白呢..
請問一下,如果剛開始的話,我在FLA上畫了一個圖像..然後應該怎樣做呢?
希望妳有時間可以回覆我呢.. 謝謝
rix
May 29th, 2009 on 2:17 pm
這個是我的E-MAIL
rriixx21@yahoo.com.hk
希望妳有時間的話可以指點我這個初學者呢^^”
May 30th, 2009 on 11:01 am
你要用Flash CS3 才可以打開啊~
September 25th, 2009 on 9:31 am
不好意思…我下載了你的FLA看
但我不太懂…我都沒看到你寫AS
似乎是在文件類別那邊有連結AS是嗎?
可以請教怎嚜使用嗎?
我看你文件類別裡的語法好像跟你上面提供的又不太相同
怎嚜靈活運用你教的這個功能呢?
可能問題有點無知…我是初學者…懇請賜教喔謝謝
方便的話可以寫信給我kokakkoo@yahoo.com
September 25th, 2009 on 11:30 pm
所有的actionscript 都是放了在classes/ 這個folder中
最好的習慣是不把actionscript 放在timeline內,這樣很難維護,也很難令人看得懂
那有MovieClip都有連結到外部的 as 檔,你在library中看movieclip的linkage就知道了。另外我也用到document class呢。