如何在Android画布上绘制具有大量基本图形的游戏

4
我在我的游戏中每一帧都会画很多线条和矩形 - 这是一个复刻老式掌上电子游戏的过程。那些主要使用粗糙点阵显示屏幕,而对于文本或某些图像则使用自定义图像的游戏。
我有一个虚拟点阵屏幕,大小为20x20个“像素”,我还在屏幕上绘制了一些7段数码管和其他东西。
根据TraceView的数据,大部分时间都花费在drawLine和drawRectangle方法上,因为它们的数量太多了。我在每一帧中都会绘制点阵显示屏的每个“像素”以及7段数码管的每个部分。
我想到了一种优化方法,只重新绘制发生变化的像素/部分,因此我保存了先前的像素/部分状态,并尝试仅重新绘制已更改的像素/部分。基本上这是一种简单的失效。 我期望的行为是Canvas在最后一帧完成绘制后保持不变,我只需要重新绘制必要的内容。 但是,我的Canvas会闪烁成黑色,并且每次屏幕状态改变时,只有点阵显示屏的像素/部分会在一帧中闪烁。我确保没有清除我的画布。
我在SurfaceView内部的Canvas上进行绘制,并在更新线程中进行,就像Lunar Lander Android示例中描述的那样。在Lunar Lander示例中,他们每一帧都重新绘制所有内容。
也许我可以在第一帧中将所有内容渲染到位图上,然后在每一帧中更新该位图? 应该使用哪种技术来编写我的paint()方法?

绘制点阵的每个像素的驱动需求是什么?为什么不创建一个图像文件并将其绘制到屏幕上。 - user432209
我在屏幕上有一个20x20像素的数组,可以打开或关闭。如果我填充一个矩形或绘制一个精灵,效果是一样的。 - Axarydax
似乎SurfaceHolder.unlockCanvasAndPost()会清除我的画布。 - Axarydax
2个回答

2

SurfaceHolder.unlockCanvasAndPost()实际上在Surface上进行页面翻转,因此即使之前的帧没有清除,你也会得到第二个最旧的帧,而不是刚刚绘制的那个。对表面进行锁定(lock())每次都会实例化一个新的画布(Canvas),这可能是在其构造函数中进行清除的原因。

最好像某人建议的那样,将图形绘制到位图(Bitmap)中,然后每次想要呈现图像到显示器时,在画布上绘制该Bitmap。你可以从位图中获取画布以进行绘制。

还有像其他人模棱两可地建议的那样,你可以为点阵显示器生成精灵,并直接从位图缓存中绘制它们,而不是使用基本的绘图命令。例如,对于点阵计算器,你可以将所有0-9生成为10个位图,然后简单地将它们放置在画布上,而不是调用一组drawLine/Rect操作。

如果上述方法仍然太慢,仍然可以使用OpenGL利用硬件加速。


好的,我在每一帧都绘制到位图上,这样它就保留了先前的状态。谢谢! - Axarydax

0

为什么不考虑使用Sprites呢?


1
请您详细说明一下,使用精灵会带来哪些改变? - Axarydax
我认为所谓的精灵,基本上就是像cris.h所说的那样,将每个可能的图像(例如数字0-9)放在一个小位图中(有时称为精灵),而不是每次绘制它。这可能会更快,因为复制位图(而不缩放它)通常比绘制一系列抗锯齿线条要快,因为机器需要“思考”的内容较少。有些机器也可以对位图绘制进行硬件加速。 - Qwertie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接