想信如果有研究開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 的效果,我會建議你跟著以下的步驟做:

  1. 準備movieclip
    先做好想在3D空間出現的movieclip,並設定好屬性,方便之後動態地用actionscript加到場景上
  2. 設計場景
    用actionscript吧movieclip動態地加到場景上,並自行定義變數去儲著物件的3D位置(x, y, z)
  3. Projection
    用我之前提供的函數,投射3D位置,得出2D位置及scale
  4. 更新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程式吧!

>> 下載例子

>> 看其他教學

  • Facebook
  • Twitter
  • del.icio.us
  • Digg
  • Google Bookmarks
  • Yahoo! Buzz
  • Live
  • RSS