AS3:如何将MovieClip 始终置于顶层

3

这个有些难以解释,我会尽力,但请耐心等待。

好的。我正在创建一款游戏,其中包括一条道路和汽车在上面随机移动(每5秒左右)。

我使用下面的代码来创建汽车及其行驶方向,并在完成屏幕横跨动画后将其移除。

 public function animateCars()
    {
        CarMC = Random_Car();

        if (CarLeft)
        {
            CarMC.x = 0;
            CarMC.y = 245;
            CarMC.name = "CarNumber_"+CarNumber;
            addChildAt(CarMC,numChildren - 1);
            MoveCar = new Tween(CarMC,"x",None.easeNone,-60,900,12,true);
            MoveCar.addEventListener(TweenEvent.MOTION_FINISH, CarFinished);
            MoveCar.start();
        }
        else
        {
            CarMC.x = 0;
            CarMC.y = 258;
            CarMC.name = "CarNumber_"+CarNumber;
            CarMC.scaleX *=  -1;
            addChildAt(CarMC,numChildren - 1);
            MoveCar = new Tween(CarMC,"x",None.easeNone,800,-260,12,true);
            MoveCar.addEventListener(TweenEvent.MOTION_FINISH, CarFinished);
            MoveCar.start();
        }
        CarNumber++;
    }

    // Loads another car when finished
    function CarFinished(e:TweenEvent):void
    {
        removeChild(getChildByName("CarNumber_"+CarNumberR));
        CarNumberR++;
    }

这一切都很完美地运作着,(嗯,有点问题,但这不是当前的问题)*。

在这个游戏中,你也可以拾取和放置物品。使用以下代码:

    function addBuilding(Text:String)
    {
        HoldingBuilding = true;
        CursorPointer.visible = false;
        CursorGrab.visible = true;
        Building = new CarWash();
        Building.x = MouseX - MouseX % size;
        Building.y = MouseY - MouseY % size2;
        Building.rotation = 0;
        addChildAt(Building,numChildren);
    }

当您将建筑物悬停在汽车上方时,汽车会保持在其下方,这一点很好。

当您将汽车放置得离道路太近时,问题就出现了。对于第一座建筑物而言,它的运作还不错,但是如果您添加第二座建筑物,汽车将会在最新的建筑物下面,并且在最旧的建筑物上面。

我无法解决如何让已放置的建筑物始终处于顶部或者让汽车处于底部

这是放置代码:

function DropBuilding(e:MouseEvent):void
        {
            if (HoldingBuilding)
            {
                if (BuildingPlacement)
                {
                    HoldingBuilding = false;
                    BuildingPlacement = false;
                    CursorPointer.visible = true;
                    CursorGrab.visible = false;

                    Building.x = MouseX - MouseX % size;
                    Building.y = MouseY - MouseY % size2;
                    Building.rotation = 0;
                    Building.transform.colorTransform = NoColour;
                    Building.removeChild(BuildingBase);
                    BuildingBase = new Sprite();
                    BuildingShaddow = new Sprite();
                    ShakeTimer.stop();
                }
                else
                {
                    ShakeTimer.start();
                }
            }
        }

提前感谢您为保持建筑物在顶部或汽车始终在底部所做的任何帮助。

Eli


*如果您想知道,我目前遇到的汽车缓动问题是每隔一段时间(我还没有弄清原因),其中一两辆汽车会停止移动5秒钟,然后消失。


@bokan 谢谢您的评论,我会在某个时候更深入地研究它。但除非那是解决我的问题的唯一方法,否则我目前不太看重它。 - Eli Stone
1
只是一条提示/技巧:addChildAt(Building, numChildren)addChild(Building) 完全相同。addChild 总是将子项放置在最上面。 - BadFeelingAboutThis
1
另一个提示,在AS3中,为了使代码更易读(当要求他人进行故障排除时非常重要),事实上的标准是实例/变量以小写字母开头,而类名以大写字母开头。 - BadFeelingAboutThis
2个回答

5
每次在你的animateCars()函数中生成一辆汽车时,你可以遍历所有子元素并将建筑物放置在汽车上方,但这有点繁琐和不必要(而且不太高效)。
这是一个更好的方法:
//create a container for the cars
var carContainer:Sprite = new Sprite();
addChild(carContainer);

//create a container for the buildings
var buildingContainer:Sprite = new Sprite();
addChild(buildingContainer);

由于您在carContainer之后添加了buildingContainer,因此它将始终处于顶部(包括其中放置的所有内容)

所以现在您的animateCars方法:

public function animateCars()
{
    CarMC = Random_Car();
    carContainer.addChild(CarMC);

    if (CarLeft)
    {
        CarMC.x = 0;
        CarMC.y = 245;
        MoveCar = new Tween(CarMC,"x",None.easeNone,-60,900,12,true);
    }
    else
    {
        CarMC.x = 0;
        CarMC.y = 258;
        CarMC.scaleX *=  -1;
        MoveCar = new Tween(CarMC,"x",None.easeNone,800,-260,12,true);
    }


    MoveCar.addEventListener(TweenEvent.MOTION_FINISH, CarFinished);
    MoveCar.start();
}

然后是你的carFinished方法:
function CarFinished(e:TweenEvent):void
{
    carContainer.removeChild((e.currentTarget as Tween).obj as Random_Car);
}

然后在你的 addBuilding 方法中,将 addChildAt(Building,numChildren); 改为:

buildingContainer.addChild(Building);

这个很好用,感谢你解释了这么多。唯一的问题是在移除缓动时出现错误。TypeError: Error #2007: Parameter child must be non-null. 我已经尝试过 carContainer.removeChild(getChildByName("CarNumber_"+CarNumberR)); 但没有解决,你认为这个问题出在哪里? - Eli Stone
@LondonDrugs_MediaServices 一份很好的解释。 - Moorthy
如果您不删除汽车并继续生成新的汽车,它们将留在内存中,逐渐减慢应用程序的速度,并在长时间后可能导致崩溃。 - BadFeelingAboutThis
@LondonDrugs_MediaServices 是的,他们就在那条线上。 - Eli Stone
谢谢!我卡了两天,这篇帖子让我解决了问题! - jdfinch3
显示剩余6条评论

1

只需使用容器 mcs 并将所有对象放在其中。这将像图层一样起作用。

mc1 地面深度 = 100
mc2 建筑深度 = 200
mc3 汽车深度 = 300
mc4 叠加层(用于分数)= 1000

具有较高深度的剪辑将位于具有较低深度的剪辑上方。我没有选择连续的深度,例如 1、2、3,因此您可以稍后在现有图层之间添加新图层。例如使用深度=150。

要了解如何为 mc 设置深度,请使用 http://www.foundation-flash.com/tutorials/changingdepths/


movieClips没有任何深度属性。虽然我同意容器是更好的选择。 - BadFeelingAboutThis
@LondonDrugs_MediaServices 我以为你知道如何做。当你使用addChildAt()时,你正在设置深度(或z-index)。我更新了答案并附上了教程。在继续使用Flash之前,请确保掌握显示树和深度的概念。这是关键的概念。 - bokan
你可以使用addChild来设置z-index,但它只是一个简单的层叠索引。与使用CSS时不同,你不能留下项目之间的空白空间以供以后使用。在Flash中,显示列表基本上是一个数组,无论该数组的顺序如何,它们都是按照顺序进行分层的。你不能像CSS那样做mc3.z-index = 300这样的事情。 - BadFeelingAboutThis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接