使用反向运动

Flash Player 10 及更高版本,Adobe AIR 1.5 及更高版本,需要 Flash CS4 或更高版本

反向运动 (IK) 是一种用于创建逼真运动的重要方法。

使用 IK 可以在一系列连接的部分(称为 IK 骨架)中创建协调运动,以便各部分以逼真的方式一起移动。骨架的各部分是其骨骼和连接。如果给定骨架的终点,IK 便可计算出达到该终点所需的连接的角度。

自己手动计算这些角度难度很大。此功能的优点在于您可以使用 Adobe® Flash® Professional 以交互方式创建骨架。然后可以使用 ActionScript 对骨架进行动画处理。Flash Professional 中附带的 IK 引擎可进行计算,以描述骨架的移动。您可以在 ActionScript 代码中使用某些参数限制移动。

此 Flash Professional CS5 版本的 IK 新增了骨骼弹簧概念,通常与高端动画应用程序相关联。与新增动态物理引擎配合使用,此功能可将动作配置得栩栩如生。并且,无论在运行时还是创作期间都可达到这种效果。

若要创建反向运动骨架,您必须拥有 Flash Professional 的许可证。

反向运动的基础知识

使用反向运动 (IK) 可以将不同的部分链接起来,使它们以逼真的方式进行相对移动,从而创建逼真的动画效果。

例如,使用 IK 时,您可以根据需要移动某条腿的连接将那条腿移动到特定的位置,从而获得所需的姿势。IK 使用一种骨骼框架,这些骨骼采用称为“IK 骨架”的结构连接在一起。 fl.ik 包可帮助您创建模仿自然运动的动画。使用该包可以对多个 IK 骨架进行无缝动画处理,而不必了解很多 IK 算法所依赖的物理知识。

使用 Flash Professional 创建 IK 骨架及其辅助骨骼和连接。然后您便可以在运行时访问 IK 类以对它们进行动画处理。

有关如何创建 IK 骨架的详细介绍,请参阅《使用 Flash Professional》中的“使用反向运动”一节。

重要概念和术语

以下参考列表中包含与此功能相关的重要术语:

骨架
一种由骨骼和联结点组成的运动链,用于在计算机动画中模拟真实运动。

骨骼
骨架中的刚性段,类似于动物骨架中的骨骼。

反向运动 (IK)
确定连接的灵活对象(称为运动链或骨架)的参数的过程。

联结点
两块骨骼接合的位置,构建在一起从而使骨骼可以移动;类似于动物的关节。

物理引擎
与物理相关联的算法包,用于为动画提供逼真的动作。

弹簧
当父骨骼移动时移动并响应、并随时间变化以增量方式下降的骨骼质量。

IK 骨架动画处理概述

在 Flash Professional 中创建 IK 骨架后,可使用 fl.ik 类在运行时限制骨架的移动、跟踪其事件并对其进行动画处理。

下图演示了一个名为 Wheel 的影片剪辑。 轴是一个名为 Axle 的 IKArmature 实例。IKMover 类会在轮子旋转时同步移动骨架。骨架中的 IKBone ( ikBone2 ) 在其尾部连接处附加到轮子。

A.
Wheel

B.
Axle

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 类的属性可以限制骨架的移动。可以基于移动的距离、迭代和时间来限制移动。

以下几对属性可强制执行这些限制。这几对属性包括一个用于指示是否限制移动的布尔值和一个用于指定限制量的整数:

布尔属性

整数属性

限制设置

limitByDistance:Boolean

distanceLimit:int

设置 IK 引擎对每次迭代移动的最大距离(以像素为单位)。

limitByIteration:Boolean

iterationLimit:int

设置 IK 引擎对每个移动执行的最大迭代次数。

limitByTime:Boolean

timeLimit:int

设置分配给 IK 引擎用于执行移动的最长时间(以毫秒为单位)。

默认情况下,所有布尔值都设置为 false ,因此除非您明确地将布尔值设置为 true ,否则移动不会受限制。若要强制执行限制,可将适当的属性设置为 true ,然后为相应的整数属性指定一个值。如果您将限制设置为某个值,却没有设置其对应的 Boolean 属性,则会忽略该限制。在这种情况下,IK 引擎继续移动对象,直至达到其他限制或 IKMover 的目标位置。

在下面的示例中,骨架移动的最大距离设置为每次迭代 0.1 个像素。每个移动的最大迭代次数设置为 10。
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 

移动 IK 骨架

IKMover 可在轮子的事件侦听器中移动轴。在轮子的每个 enterFrame 事件中,都会计算骨架的新目标位置。IKMover 使用其 moveTo() 方法将尾部连接移动到其目标位置,或是在通过其 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 的百分比值,0 表示完全刚性(默认值),100 表示很松散且由物理特性控制。具有弹簧的骨骼响应其关节的移动。如果未启用其他转换(旋转、x 或 y),弹簧设置无效。

弹簧阻尼是介于 0-100 的百分比值,0 表示没有阻力(默认值),100 表示强阻尼的。阻尼会影响从骨骼初始移动到返回静止状态所用的时间。

要了解 IKArmature 对象是否启用了弹簧,请查看对象的 IKArmature.springsEnabled 属性。其他弹簧属性和方法属于各个 IKJoint 对象。可以为关节启用角度旋转和沿 X 轴和 Y 轴的平移。您可使用 IKJoint.setSpringAngle 指定旋转关节的弹簧角度位置,使用 IKJoint.setSpringPt 指定平移关节的弹簧位置。

在以下示例中,通过名称选择了骨骼并标识了其尾关节。代码测试父骨架,以查看是否已启用弹簧,然后为关节设置弹簧属性。

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); 
}