Спрайт-лист программной резки: лучшие практики - PullRequest
3 голосов
/ 08 сентября 2011

У меня есть большая таблица спрайтов (3808x1632), состоящая из 42 кадров. Я бы представил анимацию с этими кадрами, и я использую поток, чтобы загрузить массив растровых изображений со всеми кадрами, с заставкой, ожидающей его окончания. Я не использую SurfaceView (и функцию рисования холста), я просто загружаю кадр за кадром в ImageView в моем основном макете. Мой подход похож на Загрузка большого количества изображений из таблицы спрайтов Завершение фактически занимает почти 15 секунд, что недопустимо.

Я использую такую ​​функцию:

for (int i=0; i<TotalFramesTeapotBG; i++) {
            xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
            yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
            mVectorTeapotBG.add(Bitmap.createBitmap(framesBitmapTeapotBG, xStartTeapotBG, yStartTeapotBG, frameWidthTeapotBG, frameHeightTeapotBG));
        }

framesBitmapTeapotBG - это большая таблица спрайтов. Более подробно, я прочитал в logcat, что функция createBitmap занимает много времени, возможно, потому, что таблица спрайтов слишком велика. Я где-то обнаружил, что могу создать окно на большой таблице спрайтов, используя функцию rect и canvas, создавая маленькие растровые изображения для загрузки в массив, но это не совсем понятно. Я говорю об этом посте: вырезать часть растрового изображения

У меня вопрос: как я могу ускорить вырезание таблицы спрайтов?

Edit: Я пытаюсь использовать этот подход, но не вижу окончательной анимации:

    for (int i=0; i<TotalFramesTeapotBG; i++) {
        xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
        yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
        Bitmap bmFrame = Bitmap.createBitmap(frameWidthTeapotBG, frameHeightTeapotBG, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmFrame); 
        Rect src = new Rect(xStartTeapotBG, yStartTeapotBG, frameWidthTeapotBG, frameHeightTeapotBG); 
        Rect dst = new Rect(0, 0, frameWidthTeapotBG, frameHeightTeapotBG);  
        c.drawBitmap(framesBitmapTeapotBG, src, dst, null);         
        mVectorTeapotBG.add(bmFrame);
    }

Возможно, растровое изображение bmFrame неправильно управляется.

Ответы [ 4 ]

6 голосов
/ 08 сентября 2011

Короткий ответ - лучшее управление памятью.

Загружаемый лист спрайтов огромен, а затем вы копируете его в кучу маленьких растровых изображений.Предположим, что спрайт-лист не может быть меньше, я бы предложил использовать один из двух подходов:

  1. Использование отдельных растровых изображений. Это уменьшит объем копий памяти, а такжеСколько раз Dalvik придется наращивать кучу.Однако эти преимущества могут быть ограничены необходимостью загрузки множества изображений из файловой системы вместо одного.Это было бы в случае обычного компьютера, но системы Android могут получить другие результаты, поскольку они работают без флэш-памяти.
  2. Блит прямо с вашего листа спрайта. При рисовании просто рисуйтепрямо из листа спрайта, используя что-то вроде Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint).Это сократит загрузку ваших файлов до одного большого выделения, которое, вероятно, должно произойти только один раз за время вашей деятельности.

Я думаю, что второй вариант, вероятно, лучший из двух, так как он будет прощев системе памяти и будьте меньше работать для GC.

3 голосов
/ 09 сентября 2011

Спасибо stevehb за предложение, я наконец получил его:

for (int i = 0; i < TotalFramesTeapotBG; i++) {
    xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
    yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
    Bitmap bmFrame = Bitmap.createBitmap(frameWidthTeapotBG, frameHeightTeapotBG, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bmFrame);  
    Rect src = new Rect(xStartTeapotBG, yStartTeapotBG, xStartTeapotBG+frameWidthTeapotBG, yStartTeapotBG+frameHeightTeapotBG); 
    Rect dst = new Rect(0, 0, frameWidthTeapotBG, frameHeightTeapotBG);  
    c.drawBitmap(framesBitmapTeapotBG, src, dst, null);         
    mVectorTeapotBG.add(bmFrame);
}

Время вычислений невероятно падает! :)

1 голос
/ 19 июля 2012

Я использую метод нарезки на основе строк и столбцов. Однако ваш спрайт довольно большой. Вы должны думать, что вы помещаете весь этот лист в память. 3808x1632x4 - размер изображения в памяти.

В любом случае, я делаю снимок (скажем, 128x128), а затем говорю ему, что в конструкторе Sprite (bitmap, 4, 2) есть 4 столбца и 2 строки. Тогда вы можете нарезать и нарезать кубиками на основе этого. bitmap.getWidth () / 4 и т.д ... довольно простые вещи. Однако, если вы хотите сделать что-то реальное, используйте OpenGL и используйте текстуры.

О, я также забыл упомянуть, что есть кое-что из onDraw, которое должно произойти. По сути, вы сохраняете счетчик индексов, вырезаете прямоугольник из растрового изображения и рисуете его из исходного прямоугольника в целевой прямоугольник на холсте.

1 голос
/ 08 сентября 2011

Использовать LevelListDrawable .Разрежьте спрайты на отдельные фреймы и поместите их в каталог ресурсов для рисования.Либо программно, либо с помощью списка уровней на основе xml создайте свой чертеж.Затем используйте ImageView.setImageLevel () , чтобы выбрать свой кадр.

...