Я делал в XNA шутер с видом сверху, который требует прямоугольного столкновения для карты.
Столкновения стен для карты хранятся в текстовом файле в формате: rect[0,0,1024,8]
Значения соответствуют определению прямоугольника (x, y, ширина, высота).
Я думал, что могу написать отдельное приложение, которое может неграмотно просматривать данные изображения карты, определять черные пиксели (или любой цвет стены) и создавать там прямоугольники. По сути, эта программа будет генерировать прямоугольники, необходимые для столкновения. В идеале это было бы идеально по пикселям, для чего потребовалось бы что-то вроде тысячи прямоугольников шириной в 1 пиксель, покрывающих все стены.
Есть ли способ определить, какие из этих прямоугольников (или квадратов, я бы сказал) смежны друг с другом, а затем соединить их в более крупный (но все еще покрывающий ту же площадь) прямоугольник?
НАПРИМЕР. Допустим, у меня есть стена размером 10 на 2. Программа создаст 20 различных прямоугольников, каждый высотой в 1 пиксель. Как я могу эффективно определить, что эти прямоугольники смежные, и автоматически создать прямоугольник 10 на 2, покрывающий всю стену, вместо того, чтобы иметь 20 разных маленьких прямоугольников пикселей?
РЕДАКТИРОВАТЬ: Я разработал решение, которое соответствует моим целям, мой код для дальнейшего использования приведен ниже:
//map is a bitmap, horizontalCollisions and collisions are List<Rectangle>s
for (int y = 0; y < map.Height; y++) //loop through pixels
{
for (int x = 0; x < map.Width; x++)
{
if (map.GetPixel(x, y).Name == "ff000000") //wall color
{
int i = 1;
while (map.GetPixel(x + i, y).Name == "ff000000")
{
if (i != map.Width - x)
{
i++;
}
if (i == map.Width - x)
{
break;
}
}
Rectangle r = new Rectangle(x, y, i, 1);//create and add
x += i - 1;
horizontalCollisions.Add(r);
}
}
}
for (int j = 0; j < horizontalCollisions.Count; j++)
{
int i = 1;
Rectangle current = horizontalCollisions[j];
Rectangle r = new Rectangle(current.X, current.Y + 1, current.Width, 1);
while(horizontalCollisions.Contains(r))
{
i++;
horizontalCollisions.Remove(r);
r = new Rectangle(current.X, current.Y + i, current.Width, 1);
}
Rectangle add = new Rectangle(current.X, current.Y, current.Width, i);
collisions.Add(add);
}
//collisions now has all the rectangles
По сути, он будет перебирать пиксельные данные по горизонтали. Когда он встречает пиксель стены, он останавливает счетчик и (используя цикл while) перемещает счетчик вправо, один за другим, пока он не достигнет пикселя, не являющегося стеной. Затем он создаст прямоугольник этой ширины и продолжит работу. После этого процесса появится большой список прямоугольников, каждый высотой 1 пиксель. В основном пучок горизонтальных линий. Следующий цикл будет проходить по горизонтальным линиям и, используя тот же процесс, что и выше, он обнаружит, что есть какие-либо прямоугольники с тем же значением X и тем же значением ширины под ним (y + 1). Он будет увеличиваться до тех пор, пока не останется ни одного, в котором будет создан один большой прямоугольник, а используемые прямоугольники будут удалены из списка. Окончательный результирующий список содержит все прямоугольники, из которых состоят все черные пиксели изображения (я думаю, довольно эффективно).