Я разрабатываю свой собственный физический движок для школьного проекта, и в последнее время я столкнулся с проблемой: на пиксельные столкновения на больших спрайтах мой FPS выпал ЛОТ.Оптимизация столкновений с пикселями
Вот мой код столкновения с пикселями. Прежде чем вводить следующий код, я использую Intersects()
, чтобы узнать, столкнулись ли их ограничивающие прямоугольники.
private bool PerPixelCollision(IObject a, IObject b)
{
Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height];
a.Texture.GetData(bitsA);
Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height];
b.Texture.GetData(bitsB);
// Calculate the intersecting rectangle
int x1 = Math.Max(a.Bounds.X, b.Bounds.X);
int x2 = Math.Min(a.Bounds.X + a.Bounds.Width, b.Bounds.X + b.Bounds.Width);
int y1 = Math.Max(a.Bounds.Y, b.Bounds.Y);
int y2 = Math.Min(a.Bounds.Y + a.Bounds.Height, b.Bounds.Y + b.Bounds.Height);
Color c;
Color d;
// For each single pixel in the intersecting rectangle
for (int y = y1; y < y2; ++y)
{
for (int x = x1; x < x2; ++x)
{
// Get the color from each texture
c = bitsA[(x - a.Bounds.X) + (y - a.Bounds.Y) * a.Texture.Width];
d = bitsB[(x - b.Bounds.X) + (y - b.Bounds.Y) * b.Texture.Width];
if (c.A != 0 && d.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision
{
return true;
}
}
}
// If no collision occurred by now, we're clear.
return false;
}
В примере я использую для тестирования я сбросив 4 спрайтов в другой спрайт, который представляет слово (736x79). Когда я изменяю спрайт, представляющий пол, для большего спрайта (3600x270), FPS падает. Я знаю, проблема в столкновении пикселей, потому что я использую профилировщик.
Кто-нибудь знает, как оптимизировать столкновение?
P.S .: Извините, если я не был достаточно ясен о своей проблеме. Мой английский не так хорош.
EDIT: первая проблема была решена с помощью решения, предоставленного @pinckerman, но я нашел еще один, связанный с обнаружением столкновений пикселей. Когда спрайт сталкивается с прозрачной частью текстуры, мы получаем часть, которая пересекается и проверяет все пиксели этой части. Проблема заключается в следующем: когда прозрачная часть достаточно большая, чтобы покрыть весь спрайт, я проверяю всю текстуру этого спрайта (в настоящее время использую текстуры 50x50, которые составляют 2500 пикселей). Есть ли способ не проверять всю текстуру?
Благодаря
Я не эксперт, но я не думаю, что вы должны выполнить проверку на столкновение пикселов на чем-то наподобие пола. Если вы хотите столкнуться с рельефом местности, выполните некоторую проверку столкновения полигонов. Или, если пол просто плоский, сделайте прямоугольник или даже проверку пересечения линии. Извините, но я не могу помочь вам с оптимизацией вашего алгоритма. –
не используйте это. это убийца перемирия. использовать линию, поле, круг, столкновение многоугольников. или все вместе в сочетании, но не столкновение пикселей. это просто трата ресурсов. –
Я чувствую, что нужно добавить свой голос в толпу и указать, что вы всегда будете сталкиваться с проблемами производительности, делающими такое обнаружение столкновений.Вызов 'GetData()' на текстуре _ называет конвейер рендеринга_, что предотвращает совместную работу графического процессора и ЦПУ с максимальной эффективностью. В большинстве случаев лучше использовать геометрическое обнаружение столкновений - хотя, конечно, нет ничего плохого в такого рода вещах, как учебное упражнение. См. [Эту статью] (http://blogs.msdn.com/b/shawnhar/archive/2008/04/14/stalling-the-pipeline.aspx) для получения дополнительной информации. –