返回“Flash基础理论课 - 目录”
Z排序
在添加了多个物体后代码中显现出了一个新问题——称为z排序。Z排序就像它的名字一样:物体如何在z轴上进行排序,或者说哪个物体在前面。由于物体都使用纯色,所以看起来不是很明显。为了让效果更加明显,请将 Ball3D的 init方法改为以下代码,并运行刚才那个程序:
public function init():void {
graphics.lineStyle(0);
graphics.beginFill(color);
graphics.drawCircle(0, 0, radius);
graphics.endFill();
}
通过给小球添加轮廓线,我们就可以看出哪个小球在前面了。这几乎毁掉了整个3D效果,因为现在较小的物体出现在了较大物体的前面。Z排序就是用来解决这个问题的,但不是自动的。Flash 不知道我们在模拟 3D。它只知道我们在移动和缩放影片。它也不知道我们到底是使用左手还是右手坐标系。在小球远离时应该将这个小球放在相邻小球的后面。Flash 只根据在显示列表中的相对索引进行排序。在AS 2中,z排序只需要改变影片剪辑的深度即可完成。swapDepths(深度)。深度较高的影片剪辑出现在深度较低的影片的前面。然而在AS 3中,操作会稍微有些复杂。对于显示列表没有可以任意修改的深度值。显示列表的作用更像是与个数组。列表中的每个显示对象都有一个索引。索引从 0 开始,直到列表中所有对象的个数。例如,假设在类中加入三个影片 A, B, C。它们的索引应该是0, 1, 2。无法将其中的一个影片的索引设置为100,或 -100。如果已经删除了B影片,那么这时 A和C影片的索引应该是0和1。明白了吧,在显示列表中永远没有“空间”这个概念。
根据深度,索引 0 是最低的,任何深度较高的显示对象都将出现在这个较低对象的前面。我们可以用几种不同的方法来改变物体的深度:
■ setChildIndex(child:DisplayObject, index:int) 给对象指定索引值(index)。
■ swapChildren(child1:DisplayObject, child2:DisplayObject) 交换两个指定的对象。
■ swapChildrenAt(index1:int, index2:int) 交换两个指定的深度。
使用setChildIndex 是最简单的。因为我们已经有了一个balls 数组。可以根据小球的 z轴深度从高到低来排序这个数组,然后从 balls的 0(最远的) 到 49(最近的)为每个小球设置索引。请看下面这段代码:
private function sortZ():void {
balls.sortOn("zpos", Array.DESCENDING | Array.NUMERIC);
for (var i:uint = 0; i < numBalls; i++) {
var ball:Ball3D = balls[i];
setChildIndex(ball, i);
}
}
根据数组中每个对象的 zpos属性对该数组进行排序。因为指定了数组的 DESCENDING和Array.NUMERIC,则是按数值大小反向排序的——换句话讲,就是从高到低。结果会使最远的小球(zpos 值最高的)将成为数组中的第一个,最近的将成为最后一个。
然后循环这个数组,将每个小球在显示列表中的索引值设置为与当前在数组中的索引值相同。
将这个方法放入类中,只需要在小球移动后调用它即可,将函数调用放在onEnterFrame方法的最后:
private function onEnterFrame(event:Event):void {
for (var i:uint = 0; i < numBalls; i++) {
var ball:Ball3D = balls[i];
move(ball);
}
sortZ();
}
剩下的代码与上一个例子中的相同。全部代码可在Zsort.as中找到。