检测和使用两个不同的阵列之间的碰撞检测,以消除它们的实例

检测和使用两个不同的阵列之间的碰撞检测,以消除它们的实例

问题描述:

我目前正在创建使用ActionScript flash小游戏,接受帮助的另一个问题我对这里后,我已经当移动到它的不同部分遇到的一个又一个。

I'm currently creating a small flash game using ActionScript and after receiving help for another issue I had on here, I've encountered another one when moving onto a different part of it.

这是在code我目前有:

This is the code I currently have:

var asteroidSpeed = 5;
var soundExplosion:Sound = new ExplosionSound();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKDown);

var newLaser:Array = new Array();

function onKDown(e:KeyboardEvent):void {
    keys[e.keyCode] = true;
    if (e.keyCode == 32) {
            /*laser.x = player.x + player.width/2 - laser.width/2;
            laser.y = player.y;
            addChild(laser);*/
            for (var count=0; count < 4; count++) {
                    newLaser[count] = new shipLaser();
                    newLaser[count].x = player.x + player.width/2 - newLaser.width/2;
                    newLaser[count].y = player.y;
                    addChild(newLaser[count]);
            }
    }
}

var spawnTimer:Timer = new Timer(3000); //timer will tick every 3 seconds
spawnTimer.addEventListener(TimerEvent.TIMER, spawn, false, 0, true); //let's run the spawn function every timer tick
spawnTimer.start();

var spawnPoints:Array = [0,100,200,300,400,500,550]; //your list of spawn x locations
var spawnAmount:int = 4; //how many asteroids to have on the screen at once (you could increase this over time to make it more difficult)
var asteroids:Vector.<asteroidOne> = new Vector.<asteroidOne>(); //the array for your asteroids - changed to vector for possible performance and code hint improvement (basically the same as Array but every object has to be of the specified type)

spawn(); // calling it immediately

//calling this will spawn as many new asteroids as are needed to reach the given amount
function spawn(e:Event = null):void {
if(asteroids.length >= spawnAmount) return; //let's not bother running any of the code below if     no new asteroids are needed
spawnPoints.sort(randomizeArray); //lets randomize the spwanPoints
var spawnIndex:int = 0;

var a:asteroidOne; //var to hold the asteroid every loop
while (asteroids.length < spawnAmount) {
    a = new asteroidOne();
    a.x = spawnPoints[spawnIndex];
    spawnIndex++; //incriment the spawn index
    if (spawnIndex >= spawnPoints.length) spawnIndex = 0; //if the index is out of range of the amount of items in the array, go back to the start

    a.y = -50;
    asteroids.push(a); //add it to the array/vector
    addChild(a); //add it to the display
}
}

player.addEventListener(Event.ENTER_FRAME, obstacleMove);
function obstacleMove(evt:Event):void {
for (var i:int = 0; i < asteroids.length;i++) {
    asteroids[i].y += asteroidSpeed;
    if (asteroids[i].y > stage.stageHeight || asteroids[i].x > stage.stageWidth || asteroids[i].x < -asteroids[i].width || asteroids[i].y < -asteroids[i].height) {
        //object is out of the bounds of the stage, let's remove it

                    removeChild(asteroids[i]); //remove it from the display
        asteroids.splice(i, 1); //remove it from the array/vector

                    continue; //move on to the next iteration in the for loop
    }

    if (player.hitTestObject(asteroids[i])) {
        trace("HIT");
                    removeChild(asteroids[i]);
                    asteroids.splice(i,1);
                    removeChild(player);
                    // will add end-game trigger here soon.
    }
}
}

function randomizeArray(a:*, b:*):int {
return (Math.random() < .5 ) ? 1 : -1;
}

player.addEventListener(Event.ENTER_FRAME, laserCollision);
function laserCollision(evt:Event):void {
    for (var i in newLaser) {
            for (var a in asteroids) {
                    if (asteroids[a].hitTestObject(newLaser[i])) {
                            trace("BOOM!");
                            var soundExplosion:Sound = new ExplosionSound();
                            var channel1:SoundChannel = soundExplosion.play();
                            removeChild(newLaser[i]);
                            removeChild(asteroids[a]);
                    }
            }
    }
}

addEventListener(Event.ENTER_FRAME, laserEnter);

function laserEnter(event:Event):void {
    for (var i in newLaser) {
            newLaser[i].y -= laserSpeed;
    // Moves the laser up the screen
            if(newLaser[i].y == 0) {
                    removeChild(newLaser[i]);
            }
    }
}

在从newLaser阵列实例与小行星阵列的一个实例碰撞,除去我想要做的就是无论从场景/索引(但只有两个相撞,而不是所有的人在现场)

What I want to do is when an instance from the newLaser array collides with an instance of the asteroids array, to remove both from the scene / indexes (but only the two that collided and not all of the ones on the scene).

目前,当激光击中小行星,它消除了小行星而不是激光与当前行的小行星之一会不动,然后小行星产卵的下一行,但不会向下移动。

Currently, when a laser hits an asteroid, it removes the asteroid but not the laser and one of the asteroids on the current row stops moving and then the next row of asteroids spawns but does not move down.

我得到这个错误太:

时ArgumentError:错误#2025:提供的DisplayObject必须是调用者的子级。     在flash.display使用::级DisplayObjectContainer / removeChild之()     在_8_fla :: MainTimeline / obstacleMove()

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. at flash.display::DisplayObjectContainer/removeChild() at _8_fla::MainTimeline/obstacleMove()

任何帮助将是很大的AP preciated。

Any help would be greatly appreciated.

您出错,可能是因为您正在运行的3个独立的在同一范围内enter帧处理程序,以及阵列和显示列表(即在多个引用删除项目输入框处理程序)。所以,你小行星从显示列表中删除一个,然后尝试在另一个再次将其删除。

You error, is likely because you are running 3 separate enter frame handlers in the same scope, and removing items from arrays and display lists (that are referenced in multiple enter frame handlers). So you asteroid is removed from the display list in one, and then you try to remove it again in another.

还有一大堆其他问题与你的code,这将导致错误和不想要的结果。像的(VAR我在newLasers) - 在那种循环,将参考实际的激光对象阵列的不索引。我重新分解你的code和增加了很多code意见为希望给你,你要去错误的想法:

There are also a whole lot of other issues with your code that will cause errors and undesired results. Things like for(var i in newLasers) - in that kind of loop, i will refer to the actual laser object not the index of the array. I've re-factored your code and added lots of code comments to hopefully give you an idea of where you were going wrong:

var spawnTimer:Timer = new Timer(3000); //timer will tick every 3 seconds
var spawnPoints:Array = [0, 100, 200, 300, 400, 500, 550]; //your list of spawn x locations
var spawnAmount:int = 4; //how many asteroids to have on the screen at once (you could increase this over time to make it more difficult)

var asteroidSpeed = 5;
var asteroids:Vector.<asteroidOne> = new Vector.<asteroidOne>(); //the array for your asteroids - changed to vector for possible performance and code hint improvement (basically the same as Array but every object has to be of the specified type)

var lasers:Vector.<shipLaser> = new shipLaser(); //the array of lasers
var maxLasers:int = 4; //the maximum amount lasers allowed at any given time

var soundExplosion:Sound = new ExplosionSound();

stage.addEventListener(KeyboardEvent.KEY_DOWN, onKDown);
player.addEventListener(Event.ENTER_FRAME, gameLoop);
spawnTimer.addEventListener(TimerEvent.TIMER, spawn, false, 0, true); //let's run the spawn function every timer tick
spawnTimer.start(); //start the spawn timer
spawn(); // calling it immediately


function onKDown(e:KeyboardEvent):void{
    if (e.keyCode == 32) {
        //create ONE laser per button push (instead of 4 identical lasers)

        if(lasers.length < maxLasers){ //if player hasn't reached the maximum amount of lasers available
            var tmpLaser:shipLaser = new shipLaser();
            tmpLaser.x = player.x + player.width / 2 - tmpLaser.width / 2;
            tmpLaser.y = player.y;
            addChild(tmpLaser);
            lasers.push(tmpLaser);
        }
    }
}

//calling this will spawn as many new asteroids as are needed to reach the given amount
function spawn(e:Event = null):void {
    if (asteroids.length >= spawnAmount)
        return; //let's not bother running any of the code below if no new asteroids are needed

    spawnPoints.sort(randomizeArray); //lets randomize the spwanPoints
    var spawnIndex:int = 0;

    var a:asteroidOne; //var to hold the asteroid every loop
    while (asteroids.length < spawnAmount)
    {
        a = new asteroidOne();
        a.x = spawnPoints[spawnIndex];
        spawnIndex++; //incriment the spawn index
        if (spawnIndex >= spawnPoints.length)
            spawnIndex = 0; //if the index is out of range of the amount of items in the array, go back to the start

        a.y = -50;
        asteroids.push(a); //add it to the array/vector
        addChild(a); //add it to the display
    }
}

function gameLoop(e:Event):void {
    //LOOP through all the asteroids, give it a label (asteroidLoop) so we can break/continue it inside other loops
    asteroidLoop: for (var i:int = 0; i < asteroids.length; i++) {

        //check if asteroid is out of bounds
        if (asteroids[i].y > stage.stageHeight || asteroids[i].x > stage.stageWidth || asteroids[i].x < -asteroids[i].width || asteroids[i].y < -asteroids[i].height) {
            //object is out of the bounds of the stage, let's remove it

            removeChild(asteroids[i]); //remove it from the display
            asteroids.splice(i, 1); //remove it from the array/vector

            continue; //forget the rest of the code below and move on to the next iteration in the for loop since the asteroid is gone 
        }

        //check if any lasers are colliding with this asteroid
        for (var j:int = lasers.length-1; j >= 0;j--) { //iterate over all lasers backwards
            if (asteroids[i].hitTestObject(lasers[j])){
                trace("BOOM!");
                var soundExplosion:Sound = new ExplosionSound();
                var channel1:SoundChannel = soundExplosion.play();

                //remove the asteroid
                removeChild(asteroids[i]); //remove it from the display
                asteroids.splice(i, 1); //remove it from the array/vector

                //remove the laser
                removeChild(lasers[j]);
                lasers.splice(j, 1);

                continue asteroidLoop; //break completely out of this inner for-loop (lasers) since the asteroid in the outer loop was removed, and move on to the next asteroid
            }
        }

        //check if this asteroid collides with the player
        if (player.hitTestObject(asteroids[i])){
            trace("HIT");

            //remove the asteroid
            removeChild(asteroids[i]); //remove it from the display
            asteroids.splice(i, 1); //remove it from the array/vector

            removeChild(player);

            spawnTimer.stop(); //stop spawning new asteroids

            //will add end-game trigger here soon.

            break; //break completely out of the asteroid loop if it's game over (as there's no point in checking the rest of the asteroids)

        }

        //we've made it this far, so let's just move this asteroid
        asteroids[i].y += asteroidSpeed;
    }


    for (var i:int = lasers.length-1; i >= 0;i--) { //iterate backwards
        lasers[i].y -= laserSpeed;
        // Moves the laser up the screen
        if (lasers[i].y <= 0){ //make this less than or equal to 0
            removeChild(lasers[i]); //remove the laser from the display list
            lasers.splice(i, 1); //remove the laser from the array
        }
    }
}

function randomizeArray(a:*, b:*):int {
    return (Math.random() < .5) ? 1 : -1;
}