#c #sdl #tile
#c #sdl #плитка
Вопрос:
У меня есть цикл for, который я использую для рисования сетки плиток с sdl в игре. Поскольку сетка довольно большая и содержит более 50 тыс. элементов, я хочу ее оптимизировать.
Итак, есть эта функция, которая проверяет, должен ли я рисовать плитку, поэтому, если она находится за пределами экрана, я ее игнорирую.
bool Camera::isInViewport(int amp;x, int amp;y, int amp;w, int amp;h) {
int translatedX = x offsetX;
int translatedY = y offsetY;
if (translatedX w >= 0 amp;amp; translatedX <= 0 sdl.windowWidth) {
if (translatedY h >= 0 amp;amp; translatedY <= 0 sdl.windowHeight) {
return true;
}
}
return false;
}
Я проверил эту функцию, она потребляет 15% только процессора, когда сетка большая. Можно ли сделать это быстрее? Я не могу придумать способ, который заставит его потреблять меньше ресурсов.
Комментарии:
1. Вы храните плитки в 2d-массиве или в каком-то 1d-списке (сохраняя координаты для каждой плитки)?
2. Возможно, вычтите смещения x и y (при условии, что они фиксированы на время цикла) из ширины и высоты и сохраните эти значения. Это исключило бы два добавления при вызове функции.
3. Я использую одномерный массив
4. Выровнены ли ваши плитки по сетке? Если это так, переключитесь на 2D-массив, и вам не понадобится эта функция.
Ответ №1:
С помощью этой функции вы мало что можете сделать. Не передавайте целые числа как ссылки, они внутренне передаются как указатели, и это увеличивает затраты за счет их разыменования. Объедините условия в один оператор if и начните с тех, которые, скорее всего, будут оценены как false, чтобы сделать возможным раннее короткое замыкание.
Что бы я сделал вместо этого, чтобы решить эту проблему с производительностью, так это организовать ваши плитки в 2D-массиве, где индекс и координаты могут быть вычислены друг из друга. В этом случае вам просто нужно понять границы индексов плиток, покрываемых вашим окном просмотра. Вместо проверки результата этой функции для каждой ячейки вы сможете просто указать левый и правый индекс X и верхний и нижний индекс Y. Затем просто нарисуйте их в двух вложенных циклах, подобных этому:
for (int y = topY; y <= bottomY; y)
for (int x = leftX; x <= rightX; x)
// do drawing with tile[y][x];
Другим подходом было бы кэширование предыдущих результатов. Если камера не движется, а плитки не перемещаются, то результат этой функции не изменится. Здесь может сработать простое сохранение флага, который указывает, видна ли каждая плитка (но это не очень хорошая практика в большой игре), обновляйте их при каждом перемещении камеры или пересчитывайте плитку, если она перемещается (если это возможно в вашем приложении). Тем не менее, пересчет всех флагов видимости при движении камеры будет дорогостоящим, поэтому попробуйте использовать первую оптимизацию и сократить задачу, найдя, на какой диапазон плиток вообще влияет камера