Search code examples
c#listxnacollision-detection

Enemies in a list: issue with colliding the enemies with the other enemies


I'm currently working on a game in which a list of enemies is spawned into the level randomly on the x-axis using a list up to the point of the maximum number to spawn (currently set at 10) I have a large portion of the game working however I currently have the problem that the enemies can overlap/stack on top of each other.

What I want is if the collision box of the enemy is intersecting another enemy in the list, for it to no overlap. (if that makes sense) this is the code I have for it so far.

        foreach (EnemyClass enemy1 in enemies)
        {
            if (enemy1.position.X < myPlayer.position.X - 10 && !enemy1.stopMoving)
            {
                enemy1.position.X += enemy1.amountToMove;                   
            }

            if (enemy1.position.X > myPlayer.position.X - 50 && !enemy1.stopMoving)
            {
                enemy1.position.X -= enemy1.amountToMove;
            }

            foreach (EnemyClass enemy2 in enemies)
            {
                if (enemy1 != enemy2 && enemy1.collisionBox.Intersects(enemy2.collisionBox))
                {
                    System.Console.WriteLine("Collision Detected");
                }
            }

            enemy1.collisionX = (int)enemy1.position.X;
            enemy1.Update(graphics.GraphicsDevice);
        }

Any help would be greatly appreciated.

EDIT: What I missed off was that they technically do collide, however they collide when they are 1000 pixels apart, when the sprite is actually 50 pixels wide.

EDIT: This is the changed collision code..

foreach (EnemyClass enemy in enemies)
        {
            enemy.collisionX = (int)enemy.position.X;

            if (enemy.position.X < myPlayer.position.X - 10 && !enemy.stopMoving)
            {
                enemy.position.X += enemy.amountToMove;                   
            }

            if (enemy.position.X > myPlayer.position.X - 50 && !enemy.stopMoving)
            {
                enemy.position.X -= enemy.amountToMove;
            }

            for (int i = 0; i < enemies.Count; i++)
            {
                for (int j = i + 1; j < enemies.Count; j++)
                {
                    if (enemies[i].collisionBox.Intersects(enemies[i].collisionBox))
                    {
                        System.Console.WriteLine("Collision Detected");
                    }
                }
            }

            enemy.Update(graphics.GraphicsDevice);
        }

EDIT: Here is the EnemyClass, which is where the collisionBox is contained:

public EnemyClass(Texture2D newTexture, Vector2 newPosition)
{
    texture = newTexture;
    position = newPosition;

    collisionBox = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);

    randX = random.Next(1, 3);
    speed = new Vector2(randX, 0);
}

public void Update(GraphicsDevice graphics)
{
    collisionBox = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
}

public void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(texture, position, Color.White);
}

Solution

  • It seems that the collision is being detected before all of the collision boxes have been updated.

    My suggestions for how to order things:

    1. Define the collision box in terms of position.X and position.Y so that it always accurately reflects the correct position.
    2. Update all the enemies x- and y-positions.
    3. Execute the snippet below after all the enemy positions have been updated.

    foreach (EnemyClass enemy in enemies)
    {
        if (enemy.position.X < myPlayer.position.X - 10 && !enemy.stopMoving)
        {
            enemy.position.X += enemy.amountToMove;                   
        }
    
        if (enemy.position.X > myPlayer.position.X - 50 && !enemy.stopMoving)
        {
            enemy.position.X -= enemy.amountToMove;
        }
        enemy.Update(graphics.GraphicsDevice);
    } 
    
    for (int i = 0; i < enemies.Count; i++)
    {
        for (int j = i + 1; j < enemies.Count; j++)
        {
            if (enemies[i].collisionBox.Intersects(enemies[j].collisionBox))
            {
                System.Console.WriteLine("Collision Detected");
            }
        }
    }
    

    The above code also has an advantage in not detecting the same collision twice (i.e. enemy1/enemy2 and enemy2/enemy1).