使用反向運動

Flash Player 10 以及更新的版本,Adobe AIR 1.5 以及更新的版本,需要 Flash CS4 或更新的版本

如果要創造自然的動作,反向運動 (IK) 是很有用的技巧。

IK 可讓您在名為 IK 骨架的一連串連接部分中建立座標式移動,讓各部分能以真實的方式一起移動。骨架的各個部分是由骨塊與關節所組成。指定骨架的端點時,IK 便會計算到達端點所需的關節角度。

若要手動計算這些角度,可能會花費您許多時間。這項功能的好處是,您可以使用 Adobe® Flash® Professional 以互動方式建立骨架。然後,再使用 ActionScript 將骨架製成動畫。隨附於 Flash Professional 的 IK 引擎能執行計算,以描述骨架的移動方式。您可以在 ActionScript 程式碼中透過特定參數,限制移動的方式。

IK 的 Flash Professional CS5 版本新概念是骨塊彈起,通常用於高品質的動畫應用程式。將此功能與新的動態 Physics 引擎搭配使用,可讓您設定逼真的移動方式。而且,可在執行階段和編寫期間看到此效果。

若要建立反向運動骨架,您必須取得 Flash Professional 的授權。

反向運動的基本概念

反向運動 (IK) 可讓您藉由連結各個部分,使其以真實的方式互相進行相對運動,以建立逼真的動畫。

例如,使用 IK 時,若要將一條腿移至特定位置,只要將到達該位置所需的腿關節移動加以連接即可。IK 會使用 IK 骨架結構中鍊結在一起的骨塊架構。 fl.ik 套件可以協助您建立類似自然動作的動畫。它可以讓您將多個 IK 骨架順暢地製成動畫,就算不甚瞭解 IK 演算法背後的物理觀念也沒關係。

首先,使用 Flash Professional 建立 IK 骨架與其附加的骨塊和關節,然後,再藉由存取 IK 類別,在執行階段將它們製成動畫。

如需有關如何建立 IK 骨架的詳細指示,請參閱「使用 Flash Professional」中的「使用反向運動」一節。

重要概念與術語

下列參考清單包含了與此功能相關的重要術語:

骨架
由骨塊和關節組成的運動鏈 (在電腦動畫中用來模擬自然的動作)

骨塊
就像動物骨骼中的骨頭一樣,是骨架中固定的部分。

反向運動 (IK)
彈性連接之物件 (稱為運動鏈或骨架) 的參數決定程序。

關節
就像動物的關節一樣,位於兩個骨塊連接的位置,連接之後,骨塊便可以移動。

Physics 引擎
一整套的物理相關演算法,用於提供動畫類生物的動作。

彈起
骨塊移動時、父骨塊移動後,骨塊的反應以及一段時間後逐漸消退的特性。

將 IK 骨架製成動畫概觀

在 Flash Professional 建立 IK 骨架之後,請使用 fl.ik 類別限制其移動方式、追蹤其事件,以及在執行階段將其製成動畫。

下圖顯示名為 Wheel 的影片片段。其中轉軸是名為 Axle 之 IKArmature 的實體。IKMover 類別會隨著滾輪旋轉同步移動骨架。在骨架中,IKBone ( ikBone2 ) 的尾端關節會附加至滾輪。

A.
滾輪

B.
轉軸

C.
ikBone2

在執行階段,滾輪會根據 說明動畫 所述的 __motion_Wheel 移動補間動畫來旋轉。IKMover 物件會初始化轉軸並控制轉軸的移動方式。下圖顯示兩張附加至旋轉中滾輪在不同影格時的轉軸骨架快照。

IK 骨架在兩個不同位置
在執行階段,下列 ActionScript 會執行以下動作:
  • 取得骨架及其組件的相關資訊

  • 實體化 IKMover 物件

  • 隨著滾輪旋轉一併移動轉軸

import fl.ik.* 
 
var tree:IKArmature = IKManager.getArmatureByName("Axle"); 
var bone:IKBone = tree.getBoneByName("ikBone2"); 
var endEffector:IKJoint = bone.tailJoint; 
var pos:Point = endEffector.position; 
 
var ik:IKMover = new IKMover(endEffector, pos); 
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 
 
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); 
 
function frameFunc(event:Event) 
{ 
    if (Wheel != null) 
    { 
        var mat:Matrix = Wheel.transform.matrix; 
        var pt = new Point(90, 0); 
        pt = mat.transformPoint(pt); 
         
        ik.moveTo(pt); 
    } 
}

用來移動轉軸的 IK 類別如下:

  • IKArmature:描述骨架 (由骨塊和關節組成的樹狀結構),而骨架必須使用 Flash Professional 建立

  • IKManager:文件中 IK 骨架的所有容器類別,而骨架必須使用 Flash Professional 建立

  • IKBone:IK 骨架的組成部分

  • IKJoint:兩個 IK 骨塊之間的連接點

  • IKMover:初始化 IK 骨架和控制其移動方式

如需這些類別的完整詳細說明,請參閱 ik 套件

取得 IK 骨架的相關資訊

首先,針對組成要移動之部位的骨架、骨塊和關節宣告變數

下列程式碼會使用 IKManager 類別的 getArmatureByName() 方法,將 Axle 骨架的值指定給 IKArmature 變數 tree 。其中,Axle 骨架是之前利用 Flash Professional 所建立。

var tree:IKArmature = IKManager.getArmatureByName("Axle");

同樣地,下列程式碼會使用 IKArmature 類別的 getBoneByName() 方法,將 ikBone2 骨塊的值指定給 IKBone 變數。

var bone:IKBone = tree.getBoneByName("ikBone2");

ikBone2 骨塊尾端的關節是骨架的一部分,會附加至旋轉中的滾輪。

下列程式碼會宣告 endEffector 變數,並將它指定給 ikBone2 骨塊的 tailjoint 屬性:

var endEffector:IKJoint = home.tailjoint;
pos 變數是一個點,其中儲存了 endEffector 關節的目前位置。
var pos:Point = endEffector.position;

在這個範例中, pos 是轉軸尾端與滾輪連接的關節位置。這個變數的原始值是從 IKJoint 的 position 屬性取得。

初始化 IKMover 和限制其移動方式

IKMover 類別的實體會移動轉軸。

下列程式碼會初始化 IKMover 物件 ik ,並將要移動的元素以及移動的起點傳遞至其建構函式:
var ik:IKMover = new IKMover(endEffector, pos);

IKMover 類別的各項屬性可以讓您限制骨架的移動方式。您可以根據移動的距離、循環和時間來限制移動方式。

下列屬性配對可以強制套用這些限制。這些配對是由 Boolean 值和整數組成 (分別代表示移動是否受限以及指定限制內容):

Boolean 屬性

整數屬性

限制設定

limitByDistance:Boolean

distanceLimit:int

設定 IK 引擎每次循環移動的距離上限 (以像素為單位)。

limitByIteration:Boolean

iterationLimit:int

設定 IK 引擎對每次移動所執行的循環次數上限。

limitByTime:Boolean

timeLimit:int

設定要分派給 IK 引擎執行移動的時間上限 (以毫秒為單位)。

根據預設,所有 Boolean 值都會設定為 false ,因此除非您明確將 Boolean 值設定為 true ,否則移動方式並不會受到限制。將適當的屬性設定為 true 即可強制套用限制。如果您設定了某項限制內容的值,但是卻沒有設定相對應的 Boolean 屬性,該項限制便會遭忽略。在這種情況下,IK 引擎會持續移動物件,直到到達其它限制或 IKMover 的目標位置為止。

在下列範例中,會將每次循環後骨架移動的距離上限設定為 0.1,並將每次移動的循環次數上限設定為十次。
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 

移動 IK 骨架

IKMover 會在滾輪的事件偵聽程式內移動轉軸。針對滾輪的每個 enterFrame 事件,骨架的新目標位置都會經過計算。利用骨架的 moveTo() 方法,IKMover 即可將尾端關節移至其目標位置或其 limitByDistance limitByIteration limitByTime 屬性所設定的上限。
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); 
 
function frameFunc(event:Event) 
{ 
    if (Wheel != null) 
    { 
        var mat:Matrix = Wheel.transform.matrix; 
        var pt = new Point(90,0); 
        pt = mat.transformPoint(pt); 
         
        ik.moveTo(pt); 
    } 
} 

使用彈起

Flash Professional CS5 的反向運動支援骨塊彈起。骨塊彈起可以在編寫期間設定,而且骨塊彈起特質可以在執行階段新增或修改。彈起是骨塊及其關節的一種屬性。它有兩種特質: IKJoint.springStrength 會設定彈起的幅度,而 IKJoint.springDamping 會增加強度值的阻力以及變更彈起的衰退速率。

彈起強度是百分比值,從預設值 0 (完全堅硬) 到 100 (十分鬆散,由物理性質控制)。 骨塊加上彈起會反應其關節的移動。 若未啟用其他轉移 (旋轉、x 或 y),則彈起設定將沒有作用。

彈起阻尼值是百分比值,從預設值 0 (無阻力) 到 100 (高阻尼)。 阻尼會變更骨塊的初始移動及其回到休息位置之間的時間長度。

您可以按一下 IKArmature 物件的 IKArmature.springsEnabled 屬性,便可以檢查和瞭解是否為它啟用了彈起功能。其他彈起屬性和方法屬於個別的 IKJoint 物件。可以啟用關節進行角度旋轉和沿著 x 與 y 軸轉移。您可以使用 IKJoint.setSpringAngle 來定位旋轉關節的彈起角度,並使用 IKJoint.setSpringPt 來定位轉移關節的彈起位置。

此範例會按名稱選取骨塊,並識別其 tailJoint。 程式碼會測試父骨架,瞭解是否已經啟用彈起,然後為關節設定彈起屬性。

var arm:IKArmature = IKManager.getArmatureAt(0); 
var bone:IKBone = arm.getBoneByName("c"); 
var joint:IKJoint = bone.tailJoint; 
if (arm.springsEnabled) { 
    joint.springStrength = 50; //medium spring strength 
    joint.springDamping = 10; //light damping resistance 
    if (joint.hasSpringAngle) { 
        joint.setSpringAngle(30); //set angle for rotational spring 
    } 
}

使用 IK 事件

IKEvent 類別可讓您建立包含「IK 事件」相關資訊的事件物件。IKEvent 資訊會描述因為超過指定的時間、距離或循環限制而已經終止的運動。

下列程式碼會顯示用於追蹤時間限制事件的事件偵聽程式和處理常式。這個事件處理常式會回報當超過 IKMover 的時間限制時,所引發之事件的時間、距離、循環次數和關節屬性。

var ikmover:IKMover = new IKMover(endjoint, pos); 
ikMover.limitByTime = true; 
ikMover.timeLimit = 1000; 
 
ikmover.addEventListener(IKEvent.TIME_LIMIT, timeLimitFunction); 
 
function timeLimitFunction(evt:IKEvent):void 
{ 
    trace("timeLimit hit"); 
    trace("time is " + evt.time); 
    trace("distance is " + evt.distance); 
    trace("iterationCount is " + evt.iterationCount); 
    trace("IKJoint is " + evt.joint.name); 
}