Правильная обработка изменения размера листов спрайтов в Android

У меня есть несколько листов спрайтов с одной строкой для игры, над которой я работаю. Я предоставляю их только в папке drawable-xhdpi, и я позволяю ОС изменять размер за меня на других плотностях.

При таком подходе возникает следующая проблема:

У меня есть лист спрайтов шириной 1750 (ширина xhdpi), содержащий 5 состояний. Таким образом, каждый отдельный спрайт имеет ширину 1750 / 5 = 350. На hdpi размер меняется на 1313, поэтому каждый отдельный спрайт имеет ширину 1313 / 5 = 262.6. Однако на самом деле это 262, поскольку Android не позволяет вам работать с числами с плавающей запятой в Rect, который вы должны передать как source в drawBitmap.

Проблема в том, что я не могу правильно извлечь отдельные спрайты: при их рисовании каждый последующий спрайт будет смещаться немного вправо, чего я не хочу. Есть ли способ исправить это? Я пробовал, и это работает, если я вручную изменю их размер на 1315 и предоставлю эту версию с измененным размером в drawable-hdpi, но это сильно увеличивает размер APK, и я не хочу этого делать.

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

Примечание 2: это происходит не только между xhdpi -> hdpi. Та же проблема остается при изменении размера до других классов плотности. Решение должно быть общим: для любого коэффициента изменения размера (или хотя бы 6/8, 4/8 и 3/8), для любой ширины и для любого количества отдельных спрайтов.

Чтобы лучше увидеть проблему, представьте, что это место, где нужно нарисовать (автоматически изменяемый размер спрайта):

| _ _ _ _ _ _ _ _ _ _ |

Вот как нарисован первый кадр (взятый из 0 * 262 to 0 + 262 на листе спрайтов, * представляет непрозрачную часть, которая меня волнует):

| _ _ _ _ * * _ _ _ _ |

Вот как рисуется второй кадр (взято из 1 * 262 to 262 + 262 на листе спрайтов):

| _ _ _ _ _ & & _ _ _ |

Когда должно быть:

| _ _ _ _ & & _ _ _ _ |

И так далее для каждого последующего кадра (по крайней мере, Я ДУМАЮ для каждого последующего кадра. Эффект намного менее заметен на реальном устройстве, но он есть).


person IVlad    schedule 08.06.2012    source источник


Ответы (1)


У вас возникнет эта проблема, даже если вы вручную измените размер листа спрайтов. Самый простой способ - создать лист спрайтов правильного размера для каждой сборки (или его не существует). Вам понадобится каждый кадр вашей таблицы спрайтов в виде отдельного, правильно отцентрованного и максимально возможного размера файла изображения.

Теперь вы можете использовать интерфейс командной строки ImageMagick. Используйте сценарий оболочки для

  1. Измените размер каждого большого изображения до желаемой высоты листа спрайтов (масштабируйте ширину, чтобы сохранить пропорции соотношение)
  2. Используйте команду Montage для создания листа спрайтов. Обратите внимание, что искусно написанные скрипты могут генерировать даже прямоугольные листы спрайтов.

Теперь проблем быть не должно. :) Надеюсь это поможет.

person Ani    schedule 08.06.2012
comment
Это то, что я делаю в настоящее время, но я хотел бы избежать этого, так как это почти в три раза увеличивает размер программы. - person IVlad; 09.06.2012
comment
В идеале вы бы создали APK для каждого размера экрана, не так ли? - person Ani; 09.06.2012
comment
Для каждого размера экрана да (телефоны со средним экраном + большие и большие планшеты в моем случае), но я хотел бы избежать необходимости делать это и для каждого DPI (хотя возможно ли это? Если нет решения, это не было бы слишком плохой). Кроме того, это также интересная проблема, я думаю. - person IVlad; 09.06.2012
comment
Можно ли использовать значения с плавающей запятой в качестве прямоугольника спрайта на листе спрайтов? Если вы используете OpenGL (или что-то подобное) для рендеринга спрайтов, то может быть другое решение. - person Ani; 11.06.2012
comment
Нет, прямоугольник спрайта может быть определен только целыми числами. Я не использую OpenGL. На данный момент я просто удалил листы спрайтов и использую файл для каждого кадра. - person IVlad; 11.06.2012