想要在我们点击它们时移除孩子,但索引似乎已关闭

时间:2011-12-11 14:37:04

标签: actionscript

好的,所以当我的激光击中敌人时,我想要移除激光和敌人 我的循环以某种方式在索引之外搜索并使程序崩溃。我做错了什么?

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.geom.Rectangle;
    import flash.ui.Mouse;
    import flash.utils.Timer;

    [SWF(width = 500, height = 500, frameRate = 25, backgroundColor = 0x000000)]

    public class Main extends Sprite 
    {
        private var craft:Craft = new Craft();
        private var laser:Laser;
        private var laserCollection:Vector.<Laser> = new Vector.<Laser>;
        private var laserSpeed:Number = 5;

        private var newEnemyTimer:Timer = new Timer(2000);
        private var enemy:Enemy;
        private var enemyCollection:Vector.<Enemy> = new Vector.<Enemy>;
        private var enemySpeed:Number = 5;

        public function Main()
        {
            addChild(craft);
            //Create a bounding box for the draggable area.
            var rect:Rectangle = new Rectangle(12, 460, 476, 0);
            //If you set startDrags first parameter, LockCenter to true, you don't have to explicitly set the targets position to the mouses position.
            craft.startDrag(true, rect);
            Mouse.hide();

            newEnemyTimer.start();
            newEnemyTimer.addEventListener(TimerEvent.TIMER, newEnemy);

            stage.addEventListener(MouseEvent.CLICK, shoot);

            addEventListener(Event.ENTER_FRAME, update);
        }   

        private function update(e:Event):void
        {
            updateLasers();
            updateEnemies();
            checkForHit();

            trace("lasers:" + laserCollection.length + ", enemies:" + enemyCollection.length);
        }

        private function checkForHit():void
        {
            if (laserCollection.length > 0)
            {
                for (var i:int = 0; i < laserCollection.length; i++) 
                {
                    for (var j:int = 0; j < enemyCollection.length; j++) 
                    {
                        if (laserCollection[i].hitTestObject(enemyCollection[j]))
                        {
                            removeChild(laserCollection[i]);
                            laserCollection.splice(i, 1);

                            removeChild(enemyCollection[j]);
                            enemyCollection.splice(j, 1);

                            //The program crashes here because the index is outside the reach,
                            //i.e if I have 8 laser beams out and only 3 enemies, it tries to remove enemy[8]
                            // I THINK???
                        }
                    }
                }
            }
        }

        private function updateLasers():void
        {
            if (laserCollection.length > 0)
            {
                for (var i:int = 0; i < laserCollection.length; i++) 
                {
                    if (laserCollection[i].y > 10)
                    {
                        laserCollection[i].y -= laserSpeed;
                        laserCollection[i].alpha -= 0.01;
                    }
                    else
                    {
                        //Can the problem be that I also remove the laser here?
                        //It seem to crash even if I hit an enemy at the bottom of the stage so shouldn't be.
                     removeChild(laserCollection[i]);
                     laserCollection.splice(i, 1);
                    }
                }
            }
        }

        private function updateEnemies():void
        {
            if (enemyCollection.length > 0)
            {
                for (var i:int = 0; i < enemyCollection.length; i++) 
                {
                    if (enemyCollection[i].y < 500)
                    {
                        enemyCollection[i].y += enemyCollection[i].getSpeed();
                    }
                    else
                    {
                        enemyCollection[i].y = -20;
                        enemyCollection[i].setSpeed();
                        enemyCollection[i].x = Math.random() * stage.stageWidth;
                    }
                }
            }
        }

        private function newEnemy(e:TimerEvent):void
        {
            enemy = new Enemy();
            addChild(enemy);
            enemy.x = Math.random() * stage.stageWidth;
            enemy.y = -30;
            enemyCollection.push(enemy);
        }

        private function shoot(e:MouseEvent):void
        {
            laser = new Laser();
            addChild(laser);
            laserCollection.push(laser);
            laser.x = craft.x;
            laser.y = craft.y;
        }
    }   
}

1 个答案:

答案 0 :(得分:0)

在迭代时删除数组元素会导致问题:当您在array[i]处删除元素时,以下元素将向上移动。在删除元素后,您在同一周期中仍然有array[i]的元素。当下一个循环周期开始时,i会递增 - 所以你只是跳过了一个元素。

两种可能的解决方案:

  • 如果您删除了元素,则减少计数器(在您的情况下为ij)。
  • 向后循环,因此尚未检查的元素的索引不会改变。

另一件事:此处不需要if (laserCollection.length > 0)等检查,因为如果集合为空,循环将无法运行。