Как я могу проверить, что элемент в сетке плиток находится в моем окне просмотра быстро?

#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];
 

Другим подходом было бы кэширование предыдущих результатов. Если камера не движется, а плитки не перемещаются, то результат этой функции не изменится. Здесь может сработать простое сохранение флага, который указывает, видна ли каждая плитка (но это не очень хорошая практика в большой игре), обновляйте их при каждом перемещении камеры или пересчитывайте плитку, если она перемещается (если это возможно в вашем приложении). Тем не менее, пересчет всех флагов видимости при движении камеры будет дорогостоящим, поэтому попробуйте использовать первую оптимизацию и сократить задачу, найдя, на какой диапазон плиток вообще влияет камера