2015-06-14 85 views
0

我必须模拟一些对象的运动,所以我创建了一个SurfaceView,并在其上使用专用线程绘制它们。每一个循环我调用canvas.drawColor()来清理所有以前的对象的位置并绘制新的状态。一切工作正常,帧率是体面的。在SurfaceView上绘制对象的路径

问题是:如果我想绘制物体轨迹的痕迹?在这种情况下,我必须记住每个对象的位置,并且在每个循环中绘制所有过去的数百个点的位置。这个任务保持帧率更低,在我看来,唯一的办法就是每次重绘同样的点时,这似乎是荒谬的!有一种方法可以在画布上绘制点,而不是使用每个循环的canvas.drawColor()来取消它们(这对于其他任务是必需的)?

回答

1

排序

SurfaceView的Surface使用多个缓冲区。如果它是双缓冲的,并且每帧没有清除屏幕,那么您将在一个缓冲区中显示所有奇数帧,而在另一个缓冲区中显示所有奇数帧。每当你画一个新的框架,它会翻转到另一个缓冲区,你的一半位置将消失(看起来像一切都在振动)。

您可以在每个框架上绘制每个对象的当前位置和其前一个位置。这样,两个框架都可以获得每个对象的位置。

这个想法的实际问题是你不知道Surface有多少缓冲区正在使用。如果它是三重缓冲的(这是非常可能的),那么你需要绘制当前,前一个和前一个前一个位置,以确保每个缓冲区都具有每个位置。理论上可能有更多数量的缓冲区,但不太可能。尽管如此,你并不想追求这种方法,原因很简单:当你锁定画布时,你同意修改脏区域中的每个像素。如果你不这样做,结果是不可预测的,并且你的应用程序可能会在未来的操作系统版本中被打乱。

做你想做的事情的最好方法是绘制一个屏幕外的位图,然后将整个事物涂抹到Surface上。首先,这是一个巨大的浪费,因为您只是为了几个对象而复制一个屏幕大小的位图,但很快缩减的绘制调用就会开始取胜。

创建一个与Surface大小相同的位图,然后使用constructor that takes a Bitmap创建一个Canvas。通过这个画布做所有的绘画。当你想更新屏幕时,在SurfaceView的画布上使用drawBitmap()方法。

由于性能成本的原因,我建议不要使用软件缩放 - 确保您正在进行1:1的复制。您可以使用SurfaceView表面上的setFixedSize()调用使其成为特定大小(如果有帮助的话) - 对于像素密度较大的设备,它可以提高帧速率并减少电池使用量(blog post here)。