我必须模拟一些物体的运动,所以我创建了一个SurfaceView,我用它来绘制它们。每个循环我都调用canvas.drawColor()来清理所有先前对象的位置并绘制新状态。一切正常,帧速率也不错。
问题是:如果我想绘制物体的痕迹怎么办?轨迹?在这种情况下,我必须记住每个对象的位置,并在每个循环中绘制所有过去的数百个点的位置。这个任务保持帧速率更低,我觉得荒谬,唯一的方法是每次重绘相同的点!有一种方法可以在画布上绘制点,而不是在每个循环中使用canvas.drawColor()取消它们(这是其他任务所必需的)?
答案 0 :(得分:1)
排序。
SurfaceView的Surface使用多个缓冲区。如果它是双缓冲的,并且你没有每帧清除屏幕,那么你将从一个缓冲区中的所有奇数帧和另一个缓冲区中的所有偶数帧进行渲染。每次你画一个新的框架,它都会翻转到另一个缓冲区,你的一半位置会消失(看起来一切都在振动)。
您可以在每个帧上绘制每个对象的当前位置和之前的位置。这样两个帧都可以获得每个对象的位置。
这个想法的实际问题是你不知道Surface使用了多少缓冲区。如果它是三重缓冲的(这是非常可能的话),那么你需要绘制当前,前一个和前一个先前的位置,以确保每个缓冲区都有每个位置。理论上可以使用更多数量的缓冲,但不太可能。
说完这一切之后,你不想出于一个简单的原因而采用这种方法:当你锁定画布时,你同意修改脏区域中的每个像素。如果不这样做,结果将无法预测,并且您的应用程序可能会在未来版本的操作系统中出现奇怪的现象。
做你想做的最好的方法是画一个离屏的Bitmap,然后将整个东西blit到Surface上。这首先是一个巨大的浪费,因为你只是为几个对象复制一个屏幕大小的位图,但很快就会减少绘制调用将开始获胜。
创建一个与Surface相同大小的位图,然后使用constructor that takes a Bitmap创建一个Canvas。通过此画布完成所有绘图。如果要更新屏幕,请在SurfaceView的Canvas上使用drawBitmap()
方法。
由于性能成本的原因,我建议不要使用软件缩放 - 确保您正在进行1:1的复制。您可以使用SurfaceView表面上的setFixedSize()
调用将其设置为特定大小(如果这有用) - 对于像素密度较大的设备,它可以提高帧速率并减少电池使用量(blog post here)。 / p>