Reputation:
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
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
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