#touch #collision-detection #picturebox
#коснитесь #обнаружение столкновений #picturebox
Вопрос:
Я создаю свою первую не консольную игру на Visual C #. У меня есть проигрыватель, который является полем с картинками, и препятствия, которые также являются полями с картинками. Теперь, когда я создаю препятствие (picturebox) в случайной позиции, я хотел бы проверить, касается ли оно уже другого препятствия.
Вот что у меня есть сейчас:
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 amp;amp; j != i)
{
if (IsTouching(obstacles[j], obstacles[i]))
{
tmp = false;
break;
}
}
}
if (tmp)
{
Controls.Add(obstacles[i]);
}
else
{
i--;
}
}
}
Так что это мой способ, но я знаю, что это не очень эффективно, поэтому есть идеи получше, потому что для создания этих препятствий требуется некоторое время (~ 5 секунд).
И вот мой метод IsTouching, который тоже отстой, у кого-нибудь есть идеи получше?
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 amp;amp; obj2Points[obj2Point].Y == obj1Points[obj1Point].Y)
{
return true;
}
}
}
return false;
}
Что он делает: проверяет, касаются ли края заданных двух параметров друг друга. Так что, по сути, просто обнаружение столкновений, у кого-нибудь есть идеи, потому что я новичок в этом деле?
Ответ №1:
Если мы предположим, что все препятствия сплошные (т.Е. 2 Препятствия соприкасаются, если другое находится внутри другого), вы можете использовать следующий метод:
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;
}
Я протестировал ваш текущий IsTouching
метод и обнаружил, что он дает сбой в некоторых угловых случаях, например, в этом (он утверждает, что они не соприкасаются, хотя они есть). Мой метод работает и в этих угловых случаях.
Ответ №2:
Для этого есть одна простая строка кода, но иногда она также может завершиться ошибкой для некоторых угловых элементов.
if(player1.Bounds.IntersectWith(player2.Bounds){
//Do something
}
Замените player1 на имя графического поля и то же самое на player2 ofc.