我有一个2.5D游戏(2D游戏,就像3D游戏一样),你可以不断切换深度,当玩家走在它前面并且当它走在它后面时,玩家显示在一个物体的顶部,物体显示在播放器顶部。就像当玩家的y小于对象的y时,玩家将会在对象后面,反之亦然。
我尝试使用这样的代码:
if (player.y < block.y)
{
setChildIndex(block, numChildren - 5);
}
else if (player.y > block.y)
{
setChildIndex(block, numChildren - 10);
}
但是,我看到如果我多次这样做,我需要大量的代码,显示列表会混淆并按错误的顺序排序错误的深度。有人请用最少的代码展示一个有组织的深度转换器吗?
答案 0 :(得分:1)
使用z-index stack sorting(在3D图形文献中也称为z-buffer
)used to create the 3D depth effect using just 2D techniques。
换句话说,为每个对象分配zIndex
并定期(例如onEnterFrame
事件)运行zsort
例程,该例程根据zIndex
对显示对象进行排序(顺序) {1}}价值。或者,每次在对象上发生zsort
更改时,您都可以运行zIndex
例行程序。
然后在您的代码中,您只需将zIndex
值分配给显示对象,以模拟在另一个对象之前或之后传递的对象,zsort
负责其余对象。
这里的一个技巧是在对象上分配的zIndex+1
值中有适当的间隙(即不一定是下一个zIndex
),这样可以在这些间隙之间放置对象来模拟前面的传递或在其他对象后面,没有每次都必须调整多个zIndex
值,即你只调整传入对象的一个zIndex
值 - 在另一个对象的前面或后面,而不是另一个对象的zIndex
。
连续zIndexes
之间的差距可以根据在这些对象之间任何给定时间可能存在的(其他)对象的最大数量来估算(例如,如果,最多,3
个对象可能在某个时间在任何给定对象之间,之前或之后移动,然后连续zIndexes
的间隙值将为3
,以便所有对象都可以accomodated)
这是一个非常简单的zsorter
例程,它运行periodicaly onEnterFrame
事件,并为您进行必要的深度排序(来自下面的参考文献1)
package {
import flash.display.*;
import flash.events.*;
public class DepthSortSpace extends MovieClip {
public function DepthSortSpace() {
super();
this.addEventListener( Event.ADDED_TO_STAGE, this.addedToStage, false, 0, true );
}
private function addedToStage( e:Event ) {
this.stage.addEventListener( Event.ENTER_FRAME, this.enterFrame, false, 0, true );
}
private function sortDisplayList():void {
var len:uint = numChildren;
var i,j;
for( i=0; i < len-1; i++ )
for (j=i+1; j < len; j++)
if ( getChildAt(i).y > getChildAt(j).y ) this.swapChildrenAt( i, j );
}
private function enterFrame(e:Event) {
this.sortDisplayList();
}
}
}
上面的zsorter
实际上是一个movieClip
,它充当scene
容器,您可以将显示对象添加到zsorter
movieClip,这样可以保证相应地对它们进行排序,但可以采用zsort
例程并将其应用于任何DisplayObjectContainer
或Scene
对象实例。
注意,上面的zsorter
使用bubbleSort
排序算法,其复杂度为O(n^2)
,但可以使用其他排序算法(例如{{ 3}} O(n lgn)
复杂度)
示例和参考资料