AS3 Psuedo 3D Z-Indexing

时间:2013-12-09 21:20:45

标签: actionscript-3 3d z-index

我试图在AS3中制作一个非常基本的Pseudo 3D游戏。当我按某些键时,我的角色会上下移动,但我想要发生的是当角色y位置在对象y位置上方时,角色应该出现在对象后面。 这是我目前对象类的代码:

package  {

    import flash.display.MovieClip;
    import flash.utils.getTimer
    import flash.events.Event;

    public class bushMC extends MovieClip {

        private var lastFrame:int = new int(0);
        private var dt:Number = new Number();
        private var main:Main;      

        public function bushMC(){
            main = this.parent as Main;
            stage.addEventListener(Event.ENTER_FRAME, update);
            trace(main.getChildIndex(this));
        }
        private function update(e:Event):void{          
            dt = (getTimer() - lastFrame)/30;
            lastFrame = getTimer();

            if(main.char.y + 200 < this.y + 55 && main.getChildIndex(main.char) > main.getChildIndex(this)){
                main.setChildIndex(this, main.getChildIndex(main.char)+1);

            }
            else if(main.getChildIndex(main.char) < main.getChildIndex(this)){
                main.setChildIndex(this, main.getChildIndex(main.char));
            }
        }
    }

}

我已经尝试为每次计算编辑值的加载(+ 1,-1,等于),但我似乎无法找到正确的值。我试过的一个几乎可以工作,但是当char应该在对象后面时,它只是在前面闪烁然后不断地后面。

先谢谢,凯尔。

2 个答案:

答案 0 :(得分:2)

我只是根据您的代码尝试了一些快速的模拟脚本。我得到了它的工作方式,我认为你试图让它工作:

import flash.events.Event;
import flash.display.MovieClip;
var char:MovieClip = new MovieClip();
var bush:MovieClip = new MovieClip();

char.graphics.beginFill(0xFF0000);
char.graphics.drawCircle(0, 0, 30);

bush.graphics.beginFill(0x00FF00);
bush.graphics.drawEllipse(0, 0, 40, 80);

this.addChild(char);
this.addChild(bush);

bush.x = 100+(Math.random()*350);
bush.y = 100+(Math.random()*200);

this.addEventListener(Event.ENTER_FRAME, updateYPos);

function updateYPos(e:Event):void {
    char.x = mouseX;
    char.y = mouseY;

    if(char.y < bush.y + 30 && this.getChildIndex(char) >= this.getChildIndex(bush)){
        this.setChildIndex(bush, this.getChildIndex(char));
    }
    else if(char.y > bush.y + 30 && this.getChildIndex(char) < this.getChildIndex(bush)){
        this.setChildIndex(bush, this.getChildIndex(char));
    }
}

我希望这个样本足以帮助你。所需要的只是else if上的一个额外条件而且有效。 :)

答案 1 :(得分:0)

你应该在某个地方有一个排序的灌木列表,然后按正确的顺序通过addChild()添加 - 最上面的灌木丛有最低的Z位置(子索引0或最少的灌木丛,可能有其他对象)。然后,当你的玩家移动时,你会跟踪它相对于灌木丛列表的位置,所以你不要运行完整列表检查玩家的z排序,但只检查&#34;最近的&#34;灌木可能会发生变化,然后将玩家的子指数设置为找到的值。请注意,如果您将玩家的子索引设置为布什的索引,如果您正在向前移动玩家(更大的索引),则设置为-1,因为玩家占用时布什实际上会降低一个位置显示列表中的位置,如果要将子索引设置为较低值,请设置为相等。有一个更优雅的版本,使用这样的事实,你的灌木丛在显示列表中是连续的,只有中断是播放器,虽然它会在一旦移动物体出现时耗尽。

是的,你在玩家或任何其他移动物体上运行更新,而不是在灌木丛上。

function updateZPos(e:Event):void {
    // process coordinates change
    var p:DisplayObjectContainer=this.parent; 
    // a bit faster to use function local var to get parent
    var ci:int=p.getChildIndex(this); // changeable, get current index
    var prev:DisplayObject=null;
    if(ci>0) prev=p.getChildAt(ci-1);
    var next:DisplayObject=null;
    if(ci<p.numChildren-1) next=p.getChildAt(ci+1);
    while(prev) {
        if (this.y<prev.y) {
            ci--;
            p.setChildIndex(this,ci);
            if (ci>0) prev=p.getChildAt(ci-1); else prev=null;
        } else break;
    while(next) {
        if (this.y>next.y) {
            ci++;
            p.setChildIndex(this,ci);
            if(ci<p.numChildren-1) next=p.getChildAt(ci+1); else next=null;
        } else break;
    }
}

这个函数的编写意味着p的显示列表被预先排序,并且在移动this之后将保持它的排序状态,并且适用于任何移动对象,而不仅仅是播放器。为了在不弄乱其他对象的情况下工作,将所有移动到一个容器中的内容分开,然后将其作为排序显示列表的基础。否则你的玩家最终可能会最重要,因为要检查的最后一个元素将是Y为0的得分文本字段。此外,您需要在整个移动对象集合中保持注册点的连贯位置。类,所以说灌木的基数将在Y = 0而不是在Y = 30,如你的代码所暗示的那样。然后玩家的腿也应该在Y = 0。