user1632861
user1632861

Reputation:

C# Quickly checking if two pictureboxes touch each other?

I'm creating my first non-console game in Visual C#. I have a player which is a picturebox, and obstacles which are also pictureboxes. Now when I create an obstacle (picturebox) at a random position, I would like to check if it already touches an other obstacle.

Here's what I have now:

Picturebox obstacles = new Picturebox[20];
for (int i = 0; i < obstacles.Length; i++)
{
    DateTime date = DateTime.Now;
    Random randomNumber = new Random(date.Second * (date.Minute / 2) ^ 2 + date.Hour * 123 + (i ^ 9 + i / 2));
    obstacles[i] = new PictureBox();
    obstacles[i].Image = Properties.Resources.es;
    obstacles[i].Size = new Size(25, 50);
    obstacles[i].Location = new Point(randomNumber.Next(640 - obstacles[i].Image.Width), randomNumber.Next(topBar.Height, 480 - obstacles[i].Image.Height));
    if (IsTouching(obstacles[i], player))
    {
        i--;
    }
    else
    {
        bool tmp = true;
        for (int j = 0; j < obstacles.Length; j++)
        {
            if (obstacles[j] != null && j != i)
            {
                if (IsTouching(obstacles[j], obstacles[i]))
                {
                    tmp = false;
                    break;
                }
            }
        }
        if (tmp)
        {
            Controls.Add(obstacles[i]);
        }
        else
        {
            i--;
        }
    }
}

So that's my way, but I know it's not really effective, so any better ideas, cause it takes a while (~5 seconds) to create those obstacles. And here's my IsTouching method, which also kinda sucks, anyone have better ideas?

private bool IsTouching(PictureBox obj1, PictureBox obj2)
{
    Point[] obj1Points = new Point[(obj1.Width * obj1.Height) - ((obj1.Width - 2) * (obj1.Height - 2))];
    int count = 0;
    for (int x = obj1.Left + 1; x < obj1.Left + obj1.Width - 1; x++)
    {
        obj1Points[count] = new Point(x, obj1.Top);
        obj1Points[count + 1] = new Point(x, obj1.Top + obj1.Height);
        count += 2;
    }
    for (int y = obj1.Top; y < obj1.Top + obj1.Height; y++)
    {
        obj1Points[count] = new Point(obj1.Left, y);
        obj1Points[count + 1] = new Point(obj1.Left + obj1.Width, y);
        count += 2;
    }

    Point[] obj2Points = new Point[(obj2.Width * obj2.Height) - ((obj2.Width - 2) * (obj2.Height - 2))];
    count = 0;
    for (int x = obj2.Left + 1; x < obj2.Left + obj2.Width - 1; x++)
    {
        obj2Points[count] = new Point(x, obj2.Top);
        obj2Points[count + 1] = new Point(x, obj2.Top + obj2.Height);
        count += 2;
    }
    for (int y = obj2.Top; y < obj2.Top + obj2.Height; y++)
    {
        obj2Points[count] = new Point(obj2.Left, y);
        obj2Points[count + 1] = new Point(obj2.Left + obj2.Width, y);
        count += 2;
    }

    for (int obj2Point = 0; obj2Point < obj2Points.Length; obj2Point++)
    {
        for (int obj1Point = 0; obj1Point < obj1Points.Length; obj1Point++)
        {
            if (obj2Points[obj2Point].X == obj1Points[obj1Point].X && obj2Points[obj2Point].Y == obj1Points[obj1Point].Y)
            {
                return true;
            }
        }
    }
    return false;
}

What it does: Checks if the given two parameters edges touch each other. So basically just a collision-detection, anyone have any ideas, cause I'm kinda new at this stuff?

Upvotes: 1

Views: 4678

Answers (2)

William Arnback
William Arnback

Reputation: 1

There is one simple line of code for this but it might also fail for some corner pieces sometimes.

if(player1.Bounds.IntersectWith(player2.Bounds){
  //Do something
}

Replace player1 with the name of the picture box and the same with player2 ofc.

Upvotes: -1

Smi
Smi

Reputation: 14316

If we assume that all the obstacles are solid (i.e. 2 obstacles touch if the other is inside the other), you can use the following method:

private bool IsTouching(PictureBox p1, PictureBox p2)
{
    if (p1.Location.X + p1.Width < p2.Location.X) 
        return false;
    if (p2.Location.X + p2.Width < p1.Location.X)
        return false;
    if (p1.Location.Y + p1.Height < p2.Location.Y)
        return false;
    if (p2.Location.Y + p2.Height < p1.Location.Y)
        return false;
    return true;
}

I tested your current IsTouching method and found out that it fails in some corner cases, such as in this one (it claims they are not touching although they are). My method works in these corner cases too.

Upvotes: 3

Related Questions