【发布时间】:2014-03-04 00:01:13
【问题描述】:
通过使用 SurfaceView,我正在尝试为在画布中移动的对象制作淡入淡出效果。然后我有一个背景,在每一帧上它都会用一个 alpha 值绘制到画布中(所以之前绘制的所有内容都会褪色),然后绘制对象的下一个位置。
我遇到的问题是,当使用 alpha 值多次绘制背景时,颜色会变得离散。一些图像;顶部的第一帧具有连续的颜色,而底部的帧相同,但之后的许多帧(~50),颜色变得离散。
我放了一些我的代码。初始化部分:
// Inited somewhere in the start of the app
Bitmap bmp = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas bmpCanvas = new Canvas(bmp);
Paint backgroundPaint = new Paint();
Bitmap background = Bitmap.createBitmap(width, height, Config.ARGB_8888);
// Draw the background image into background
bmpCanvas.drawBitmap(background, 0, 0, backgroundPaint);
backgroundPaint.setAlpha(0x10);
然后我有一个线程,它在他的run方法中将帧率设置为30,并调用doDraw(Canvas c)方法来绘制bmpCanvas中的所有内容。然后它将其位图(bmp)绘制到场景画布中(如果我不这样做,那么我会因为 SurfaceView 的双缓冲区而抖动)
private void doDraw(Canvas c){
c.drawBitmap(background, 0, 0, backgroundPaint);
// Draw all the objects
}
我尝试通过尝试所有 PorterDuffXFermode 来更改 backgroundPaint 的 Xfermode 来解决它,但似乎没有人适合我。
==============解决方案=========================
受 Lorne Laliberte 的启发,我所做的是双缓冲以使其更快。
基本上我将背景创建为位图。然后我设置了 2 个与背景具有相同宽度和高度的空位图,并为它创建了 2 个画布。我还保留了一个索引,告诉我应该在哪个画布上绘制(称之为iCanvas)。
现在不需要另一个位图来避免 SurfaceView 的双缓冲区,因为我将再次绘制所有内容(所以没有闪烁)。
然后我所做的是在每一帧中,清除 actual 画布,并使用带有一些 alpha(例如 0xE0)的 Paint 绘制 previous,然后在此画布上绘制对象。
然后只需将背景绘制到SurfaceView 的画布,然后是actual 画布。最后只需切换索引iCanvas。
我认为这比记住对象的所有先前位置并使用不同的 alpha 再次绘制它们要快得多。这 100% 有效,就像在每一帧中一样,被绘制的对象会逐渐消失,我们不会在同一背景上重新绘制半透明背景。
【问题讨论】: