Nathan
Nathan

Reputation: 536

How to check if Objects in Array are Colliding with each other?

Hi everyone I hope I asked the correct question. So Basically I have a Movie Clip named mcLiquidWastethat I add to the stage. There are 3 different positions on the stage that they come out of. In my main engine class I have a for loop set up that controls how many come out at a time like so:

    private function addLiquidWaste():void 
    {
        //Duplicate Tween for repeat
        TweenLite.delayedCall(randomNumber(nDifficulty1, nDifficulty2), addLiquidWaste);
        //determine how many come out at a time 
        numberOfLiquids = randomNumber(1, 3);
        //iterate through for loop
        for (var i = 0; i < numberOfLiquids; i++)
        {
            //Instantiate liquid
            var liquid:mcLiquidWaste = new mcLiquidWaste();
            //Add liquid to stage
            stage.addChild(liquid);
            //push liquid MC into array
            aLiquidArray.push(liquid);
        }
    }

The issue I am having is that sometimes when they come out they overlap each other for instance say 3 come out at the same time well 2 of those might come out in the same position which I dont want. I want to somehow process that if they come out in the same position and not in a different slot on the stage then have them removed or have the overlapping movie clip go to a different position. That is why I was thinking of checking if 2 of the objects in the array are touching then remove those somehow.

Here is what my mcLiquidWaste class looks like and how they are added to the stage in different positions.

private function init():void 
    {
        nSpeed = 4;

        var liquidPosition:Number = randomNumber(1, 3);

        if (liquidPosition == 1) //Position Lava to the Left Hole
        {
            this.y = (stage.stageHeight / 2) - 200;
            this.x = (stage.stageWidth / 2) - 150;
        }
        if (liquidPosition == 2) //Position Lava to the Middle Hole
        {
            this.y = (stage.stageHeight / 2) - 200;
            this.x = (stage.stageWidth / 2) ;
        }
        if (liquidPosition == 3) //Position Lava to the Right Hole
        {
            this.y = (stage.stageHeight / 2) - 200;
            this.x = (stage.stageWidth / 2) + 150;
        }

        addEventListener(Event.ENTER_FRAME, liquidHandler);
    }

as you can see in my liquid waste class they are added to the left, middle, and right of the stage. Please ANY help would be appreciated thank you!

How I managed to fix it

for (var a:int = 0; a < aLiquidArray.length - 1; a++) 
        {
           var l1:mcLiquidWaste = aLiquidArray[a];

           for (var j:int = a + 1; j < aLiquidArray.length; j++) 
           {
              var l2:mcLiquidWaste = aLiquidArray[j];
              if (l1.hitTestObject(l2))
              {
                 //do something on collision
                 l2.destroyLiquid();
              }
           }
        }

Upvotes: 1

Views: 182

Answers (1)

null
null

Reputation: 5255

The whole "try until something works" approach is not ideal. In theory, the code could run forever, but that's not very probable.

The core problem is that you give up on the deterministic behaviour of the program.

or have the overlapping movie clip go to a different position.

You have this code that makes it equally likely to spawn at either of the 3 positions:

var liquidPosition:Number = randomNumber(1, 3);

    if (liquidPosition == 1) //Position Lava to the Left Hole
    {

Now if you go in after the fact and change the position, this code becomes meaningless.

Let's say you have a non-equal distribution. Say for example, on the super-extreme difficulty, the mcLiquidWaste is spawned mostly in the position that's closest to the player. So they have a shorter distance to get to the player, which would make it more difficult. Now you don't want to change the position.

I would not recommend changing the position after it is determined. It's better to spawn the mcLiquidWaste in a way that they cannot overlap.

There's your problem

Here is what my mcLiquidWaste class looks like and how they are added to the stage in different positions.

private function init():void 
{
    nSpeed = 4;

    var liquidPosition:Number = randomNumber(1, 3);

    if (liquidPosition == 1) //Position Lava to the Left Hole
    {
        this.y = (stage.stageHeight / 2) - 200;
        this.x = (stage.stageWidth / 2) - 150;
    }
//etc... 

The fact that each individual object determines its position on its own is the problem. The objects don't know each other. And they shouldn't know each other either.

The positioning of the objects should happen in the class that knows all the objects.

solution

Place the objects in a pattern, so that they cannot overlap. One example is to put them all on a circle that's big enough so that they don't overlap.

Here's an example class:

package
{
    public class SpawnPoint
    {
        private var _position:Point;

        public SpawnPoint(position:Point)
        {
            _position = position;
        }

        public spawn (amount:uint):Array
        {
            var waste:mcLiquidWaste;
            var wastes:Array = [];

            // the trivial case of 1, spawn at the position
            if(amount == 1)
            {
                waste = new mcLiquidWaste();

                waste.x = _position.x;
                waste.y = _position.y;

                wastes.push(waste);

                return wastes;
            }

            // if there are more than 1, distribute them on a circle around position

            /*  the radius depends on the size of mcLiquidWaste (and the amount)
                you have to either play around with that value or determine it  
                from the size dynamically
            */
            var radius:Number = 25;

            /*  the angle depends on the number of mcLiquidWaste
                you have to either play around with that value or determine it  
                from the size dynamically
            */
            var angle:Number = 2 * Math.PI / amount; 

            for (var i = 0; i < amount; i++)
            {
                waste = new mcLiquidWaste();

                var posititionOnCircle:Point = Point.polar(radius, i * angle).add(_position);

                waste.x = posititionOnCircle.x;
                waste.y = posititionOnCircle.y;

                wastes.push(waste);
            }

            return wastes;
        }
    }
}

This won't compile, but you get the idea: use a radius and an angle to create positions that lie on a circle. The usage would look something like this:

//create spawn point
var leftHole:SpawnPoint = new SpawnPoint(new Point((stage.stageWidth / 2) - 150, (stage.stageHeight / 2) - 200));

// creation of objects
var spawnedObjects:Array = leftHole.spawn(4);

// adding to display list
for (var i:uint = 0; i < spawnedObjects.length; ++i)
{
    addChild(spawnedObjects[i]);
}

Upvotes: 2

Related Questions