在ActionScript3中,addChild / removeChild和显示列表顺序有问题

时间:2014-07-24 17:24:08

标签: actionscript-3 flash

我正在开展一个项目,其中包括一个玩家可以扔石头的湖牌,这反过来又会导致章鱼从每个石头击中湖面的位置上升到湖中。

在石头击中之后和章鱼出现之前,石头上还会出现飞溅的符号。

屏幕上可能会同时出现很多章节,需要在显示列表中对它们进行排序,以便那些应该显得更加突出的章节落后于其他章节。

这些符号的每个实例只能播放一次然后被删除。

我的代码使用了不同的添加/删除子方法以及循环,条件和数组,我在各种教程和论坛的帮助下将它们放在一起。

我遇到的问题是,当您快速连续两次或多次点击湖面时,石头和飞溅符号不能正确移除并经常保持循环。

这是我正在使用的代码。有什么想法吗?

var stone:Stone;
var stoneSplash:StoneSplash;
var octopus1:Octopus1;
var octopus2:Octopus2;
var whichOctopus:Array = [addOctopus1, addOctopus2];
var octopusScale:Number;
var octopusContainer:MovieClip = new MovieClip;

lake.lakeHitArea.addEventListener(MouseEvent.CLICK, onClickLake);

//Add octopusContainer to the stage's display list just above the Lake
addChildAt(octopusContainer,getChildIndex(lake) + 1);
octopusContainer.x = 0;
octopusContainer.y = 0;

function onClickLake(e:MouseEvent):void
{
    trace("CLICK");
    throwStone(mouseX, mouseY);
}
function throwStone(stonePositionX:int, stonePositionY:int)
{
    stone = new Stone();
    stone.x = stonePositionX;
    stone.y = stonePositionY;
    addChild(stone);
    addEventListener(Event.ENTER_FRAME, removeStone);
}
function removeStone(e:Event):void
{
    var count:int = numChildren;
    var children:Array = [count];

    //load all the children of the component into an Array
    for (var i:int=0; i<count/* -1*/; i++)
    {
        children[i] = getChildAt(i/* + 1*/);
    }

    for (i=0; i<count/* - 1*/; i++)
    {
        if (children[i] is Stone)
        {
            if (children[i].currentFrameLabel == "Splash")
            {
                stoneSplash = new StoneSplash();
                octopusContainer.addChild(stoneSplash);
                stoneSplash.x = children[i].x;
                stoneSplash.y = children[i].y;
            }
            if (children[i].currentFrameLabel == "end")
            {
                octopusContainer.removeChild(stoneSplash);
                var positionX:int = children[i].x;
                var positionY:int = children[i].y;
                addOctopus(positionX, positionY);
                removeChild(children[i]);
            }
        }
    } 
}
function addOctopus(positionX, positionY)
{
    var o:int = Math.round(randomNumber(0,1));
    whichOctopus[o](positionX, positionY);   
    reorderDisplayList();
    addEventListener(Event.ENTER_FRAME, removeOctopus);
}
function addOctopus1(positionX: int, positionY:int):void
{
//  if (whichOctopus1 == true)
//  {
//      var octopus:* = octopus1_1;
//  }
//  else
//  {
//      octopus = octopus1_2;
//  }
    octopus1 = new Octopus1();
    var octopus:DisplayObject = octopus1;
    octopusContainer.addChild(octopus);
    octopus.x = positionX;
    octopus.y = positionY;
    octopusScale = randomNumber(0.5,0.85);
    octopus.scaleX = octopusScale;
    octopus.scaleY = octopusScale;
    trace("children = " + octopusContainer.numChildren);
    testPosition(octopus);
}
function addOctopus2(positionX: int, positionY:int):void
{
//  if (whichOctopus2 == true)
//  {
//      var octopus:* = octopus2_1;
//  }
//  else
//  {
//      octopus = octopus2_2;
//  }
    octopus2 = new Octopus2();
    var octopus:DisplayObject = octopus2;
    octopusContainer.addChild(octopus);
    octopus.x = positionX;
    octopus.y = positionY;
    octopusScale = randomNumber(0.25,0.5);
    octopus.scaleX = octopusScale;
    octopus.scaleY = octopusScale;
    trace("children = " + octopusContainer.numChildren);
    testPosition(octopus);
}
function testPosition(octopus:Object):void
{
    trace(octopus)
    for (var i:int = 0; i < 200; i++)
    {
        if (lake.hitTestPoint(octopus.x + octopus.hitTestBox1.x * octopus.scaleX,octopus.y + octopus.hitTestBox1.y * octopus.scaleY,true))
        {
            break;
        }
        else
        {
            octopus.x++;
        }
    }
    for (i = 0; i < 100; i++)
    {
        if (lake.hitTestPoint(octopus.x + octopus.hitTestBox2.x * octopus.scaleX,octopus.y + octopus.hitTestBox2.y * octopus.scaleY,true))
        {
            break;
        }
        else
        {
            octopus.y--;
        }
    }
    for (i = 0; i < 200; i++)
    {
        if (lake.hitTestPoint(octopus.x + octopus.hitTestBox3.x * octopus.scaleX,octopus.y + octopus.hitTestBox3.y * octopus.scaleY,true))
        {
            break;
        }
        else
        {
            trace(i);
            octopus.x--;
        }
    }
    for (i = 0; i < 100; i++)
    {
        if (lake.hitTestPoint(octopus.x + octopus.hitTestBox1.x * octopus.scaleX,octopus.y + octopus.hitTestBox1.y * octopus.scaleY,true))
        {
            break;
        }
        else
        {
            octopus.y--;
            trace(i);
        }
    }
}
function randomNumber(min:Number, max:Number):Number
{
    return Math.random() * (max - min) + min;
}
function reorderDisplayList():void
{
    //the number of children in our component
    var count:int = octopusContainer.numChildren;
    var children:Array = [count];

    //load all the children of the component into an Array
    for (var i:int=0; i<count; i++)
    {
        children[i] = octopusContainer.getChildAt(i);
    }

    //sort the Array children based on their 'y' property
    children.sortOn("y", Array.NUMERIC);
    //re-add the children to the component ;
    //in the order of the sorted Array we just created.
    //When we add the children using 'addChild' it will 
    //be added at the top of the component's displaylist
    //and will automatically be removed from its original position.
    for (i=0; i<count/* - 1*/; i++)
    {
        if (children[i] is Octopus1 || children[i] is Octopus2)
        {
//          trace("child = " + children[i] + " at i: " + i);
            octopusContainer.removeChild(children[i]);
            octopusContainer.addChild(children[i]);
        }
    } 
}
function removeOctopus(e:Event):void
{
    var count:int = octopusContainer.numChildren;
    var children:Array = [count];

    //load all the children of the component into an Array
    for (var i:int=0; i<count/* -1*/; i++)
    {
        children[i] = octopusContainer.getChildAt(i/* + 1*/);
    }

    for (i=0; i<count/* - 1*/; i++)
    {
        if (children[i] is Octopus1 || children[i] is Octopus2)
        {
            trace(i);
            trace("Is an octopus");
            if (children[i].currentFrame >= 202)
            {
                octopusContainer.removeChild(children[i]);
            }
        }
    } 
}

我非常感谢任何帮助我克服这个障碍并继续我的项目的建议。

提前谢谢。

克里斯柯林斯。

1 个答案:

答案 0 :(得分:0)

您的问题(或至少其中一个)是您的代码只会移除最新的StoneSplash。因此,如果您在启动和结束动画之间单击很多次,则只会删除最后一次单击的动画。

这是因为您使用全局var(stoneSplash)来引用splash,它会被覆盖到新的。你需要在石头本身上添加一个启动参考,或者创建一个字典,这样你才能知道哪个石头与哪个石头相关。

这是一种方式:

if (children[i].currentFrameLabel == "Splash")
        {
            stoneSplash = new StoneSplash(); 
            MovieClop(children[i]).stoneSplash = stoneSplash; //add a reference the splash on the stone itself

然后,而不是octopusContainer.removeChild(stoneSplash);做:

octopusContainer.removeChild(MovieClop(children[i]).stoneSplash);

这样你就可以去掉这块石头上的正确喷溅物。


这将是一种更清晰的方法来构建它而不是使用输入框处理程序:

  1. Stone班级时间轴上,将以下代码分别放在Splash和End框架上:

    启动框架:this.dispatchEvent(new Event("Splash"));

    结束框架:this.dispatchEvent(new Event("End"));

  2. 在创建新的石头实例时监听这些事件:

    stone = new Stone();
    stone.x = stonePositionX;
    stone.y = stonePositionY;
    stone.addEventListener("Splash", splashHandler,false,0,true);
    stone.addEventListener("End",removeStone,false,0,true);
    addChild(stone);
    
  3. 恰当回应这些事件:

    function splashHandler(e:Event):void {
        var stone:Stone = e.currentTarget as Stone;
        stoneSplash = new StoneSplash();
    
        //you need a reference to the splash from the stone class - it would be best to create a class file and add a public property called splashObj and then just use stone.splashObj = new StoneSplash();
        MovieClip(stone).stoneSplash = stoneSplash;  //so on the end event we can read this var to remove stoneSplash
        octopusContainer.addChild(stoneSplash);
        stoneSplash.x = stone.x;
        stoneSplash.y = stone.y;
    }  
    
    function removeStone(e:Event):void {
        var stone:Stone = e.currentTarget as Stone;
        octopusContainer.removeChild(MovieClip(stone).stoneSplash);
        addOctopus(stone.x, stone.y);
        removeChild(stone);
    }