我有一个由42帧组成的大型spritesheet(3808x1632)。 我会用这些帧呈现一个动画,我使用一个线程来加载一个包含所有帧的位图数组,并用一个闪屏等待它的结束。 我没有使用SurfaceView(和画布的绘图功能),我只是在我的主布局中的ImageView中逐帧加载。 我的方法类似于Loading a large number of images from a spritesheet 完成实际上需要将近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是一个很大的spritesheet。 看得更深,我在logcat中读到createBitmap函数需要花费很多时间,可能是因为spritesheet太大了。 我找到了一个可以在大spritesheet上创建窗口的地方,使用rect函数和canvas,创建要在数组中加载的小位图,但它并不是很清楚。我在谈论那篇文章:cut the portion of bitmap
我的问题是:如何加速精灵切割?
编辑: 我正在尝试使用这种方法,但我看不到最终的动画:
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。
答案 0 :(得分:6)
简短的回答是更好的内存管理。
你加载的精灵表是巨大的,然后你将它复制成一堆小位图。假设精灵表不能更小,我建议采用以下两种方法之一:
Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
等内容直接从精灵表中绘制。这会将文件加载减少到一个大的分配,可能只需要在活动的生命周期中发生一次。我认为第二种选择可能是两者中较好的选择,因为它在内存系统上会更容易,并且对GC的工作也会减少。
答案 1 :(得分:3)
感谢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);
}
计算时间令人难以置信! :)
答案 2 :(得分:1)
使用LevelListDrawable。将精灵切割成单独的框架并将它们放入可绘制的资源目录中。以编程方式或通过xml based level-list drawable创建您的drawable。然后使用ImageView.setImageLevel()选择你的框架。
答案 3 :(得分:1)
我使用基于行和列的切片方法。但是你的精灵表相当庞大。你必须认为你将整张纸放入记忆中。 3808x1632x4是内存中图像的大小。
无论如何,我做的是拍摄一张图片(比方说128x128),然后告诉它Sprite(bitmap,4,2)构造函数中有4列和2行。然后你可以根据它切片和切块。 bitmap.getWidth()/ 4等...非常简单的东西。但是,如果你想做一些真正的东西,请使用OpenGL并使用纹理。
哦,我也忘了提到有一些onDraw需要发生的东西。基本上你保留一个索引计数器并从位图中切出一个矩形,并将其从源矩形绘制到画布上的目标矩形。