В браузере лучше всего использовать одну огромную таблицу спрайтов или много (10000) разных PNG?

33

Я создаю игру в jQuery, где я использую около 10000 плиток 32x32. До сих пор я использовал их все по отдельности (без спрайт-листа). Средняя карта использует около 2000 плиток (иногда повторно используемые PNG, но все отдельные div), а производительность варьируется от стабильной (Chrome) до немного запаздывающей (Firefox). Каждый из этих элементов позиционируется абсолютно с использованием CSS. Их не нужно обновлять каждый тик, только когда загружается новая карта.

Будет ли для производительности лучше использовать методы spritesheet для элементов div, использующих CSS-позиционирование фона, как это делает gameQuery?

Заранее спасибо!

Ник
источник
3
Где, черт возьми, вам нужно 10 000 плиток для карты? Я предлагаю вам не загружать / рисовать всю карту на стороне пользователя. Показать только часть, которая видна. Когда пользователь переместится, загрузите следующий раздел. Как работает каждая 3D графика.
Deele
Средняя карта использует 2000 различных плиток или всего 2000 плиток? Насколько велики карты, которые вы создаете?
Ник Ларсен
Рассматривали ли вы использование одного или нескольких больших изображений в качестве фона и выполнение полигонального обнаружения столкновений для границ?
SAHornickel

Ответы:

50

Мое предложение

Слишком много небольших PNG-файлов приведет к большим накладным расходам в сети (из-за размера HTTP-запросов, но также и из-за заголовка PNG и, что еще важнее, из-за невозможности эффективного сжатия). С другой стороны, один очень большой PNG имеет недостатки, которые требуют некоторого времени для загрузки, и он должен постоянно находиться в памяти (40 мегабайт на 10 000 плиток) в непрерывном куске памяти.

Я рекомендую золотую середину: несколько PNG разумного размера, например, 1024 плитки размером 32 × 32 . Может быть сгруппированы по темам (например, PNG с лесными плитками, одна с горными плитками, другая с городскими плитками - я не знаю тему вашей игры, но вы поняли идею).

Замечание об эффективности кеша

Из-за эффективности доступа к памяти, вы никогда не должны делать свои спрайт-листы слишком широкими. Блики плитки из изображения 128 × 8192 всегда будут быстрее, чем блики из изображения 8192 × 128.

Представьте, что вы хотите скопировать первую плитку на изображении размером 8192 × 128. Для простоты предположим, что 1 пиксель равен 1 байту. Первые две строки пикселей расположены таким образом (ячейки содержат номер байта в памяти):

┌────┬────┬───┬────┬──────────┬─────┐
  0   1 │...│ 31    ....    8191 1st line of pixels: bytes 0 to 8191
├────┼────┼───┼────┼──────────┼─────┤
81928193│...│8223   ....   16383 2nd line of pixels: bytes 8192 to 16383
├────┼────┼───┼────┼──────────┼─────┤
 ..  .. │...│ ..    ....    ... 

Таким образом, чтобы убрать первую строку первого заголовка, механизм браузера будет извлекать байты 0в31 . Для блитирования на вторую линию , она будет получать байты 8192к8223 , и так далее до 32 - й линии , где байтов 253952для253983 извлекаются.

Общее количество обработанных байтов будет 32 × 32. Однако общий объем памяти составляет более 253984 байта. На современном процессоре это означает 32 или 33 остановки кеша . Напротив, если бы изображение было 128 × 8192, диапазон памяти был бы только 4000 байтов, что означает не более двух остановок кэша.

Поскольку современные процессоры очень быстрые, кэш-память стоит очень дорого и требует больших вычислений. Таким образом, использование изображения 128 × 8192 вместо изображения 8192 × 128 потенциально в 8 раз быстрее, по крайней мере в теории. На практике это будет зависеть от того, как будет реализован блитинг: возможно, что базовый механизм сам разбивает изображения на фрагменты, чтобы уменьшить проблему.

Это нелегко объяснить правильно, и я не ожидал, что укажу много. Я надеюсь, что это имеет смысл!

Сэм Хоцевар
источник
4
«Обратите также внимание на то, что из-за эффективности доступа к памяти вы никогда не должны делать свои спрайт-листы слишком широкими. Перекрытие фрагментов изображения 128 × 8192 всегда будет быстрее, чем блики изображения 8192 × 128». - любопытство, не могли бы вы уточнить, пожалуйста? :)
Гримшоу
@DevilWithin: я пытался объяснить проблему; дайте мне знать, если я достаточно ясно
Сам Хочевар
Эффективность кеша впечатляет. Есть ли у вас какие-либо цифры на разницу, что это делает в отношении частоты кадров?
Грегори Эйвери-Вейр
Является ли это проблемой, похоже на конкретную реализацию, но если API, такой как OpenGL, действует на текстуры таким образом, важно принять это во внимание, спасибо :)
Grimshaw
2
@DevilWithin: то, что я написал, действительно только для CPU - GPU, будучи массивно параллельным, имеет очень разные настройки кэша и будет хранить текстуры, используя собственный внутренний формат, оптимизированный для произвольного доступа. По этой причине в OpenGL рекомендуются квадратные текстуры со степенью двух, и я бы следовал этому правилу и для наборов плиток.
Сам Хочевар
5

Одна огромная таблица спрайтов (вероятно) даст вам лучшую производительность, просто потому, что одной из главных причин отставания является обратная передача от запроса браузера к серверу и браузеру. 10000 HTTP-вызовов займет намного больше времени, чем 1 HTTP-вызов, который возвращает файл, который на 10000 больше.

Могут быть и другие вещи, которые вы можете использовать для уменьшения задержки, в зависимости от структуры игры и HTML, который вы создаете.

thedaian
источник