这是我正在做的一个 NES 模拟器项目。每秒我需要绘制大约 60 次屏幕才能获得准确的仿真,这意味着我每秒至少要绘制 256 * 240 * 60 像素。对于绘图,我使用的是画布。在每一帧上,我都会浏览 256 * 240 像素的数据并将它们绘制在屏幕上。不出所料,这太可怕了。我的模拟器每秒绘制不到一帧
public class GameCanvas extends View{
public void drawSprite(int x, int y, Olc2C02A.Sprite sprite, Canvas canvas){
for (int ir = 0; ir < sprite.height; ir++){
for (int ic = 0; ic < sprite.width; ic++){
Olc2C02A.Pixel p = sprite.getPixel(ic, ir);
if (p.a != 0){
int pr = p.r, pg = p.g, pb = p.b, pa = p.a;
painter.setColor(Color.argb(pa, pr, pg, pb));
canvas.drawPoint((x + ic), (y + ir), painter);
}
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#000000"));
drawSprite(0, 0, this.gameScreen, canvas);
}
}
上面的代码是我的代码的一个稍微简化的版本。在这段代码中,我只是逐个像素地绘制,而忽略了每个像素的实际大小,如果我考虑根据运行此应用程序的屏幕大小调整框架大小,则需要这些像素。 精灵是一个 256x240 大小的像素对象数组。这是我为存储每个像素的颜色值而制作的自定义类。 因此,不幸的是,仅仅轻微的性能提升对于模拟器来说是不够的。如果我想让我的模拟器正常运行,我需要每秒至少绘制 30 帧。 对于适合我的 android studio 项目的任务,我还可以使用哪些其他替代方法。
没有人绘制像素。所有游戏都使用 OpenGL。
甚至 Android 应用程序的 GUI(按钮/编辑/图片/...)也是使用 OpenGL 绘制的。
当你逐像素绘制时,你正在使用 CPU 来渲染图形。您根本没有使用 GPU(显卡)。所以这永远行不通。
你必须使用 GLSurfaceView。您必须使用 GLES20, GLES30, ...
中定义的 OpenGL 函数NES 图形基于二次条纹(纹理)。这些条纹被加载到 NES 显卡中,然后可以由 GPU 内部的 CPU 调整大小、旋转和变换。所以CPU可以向GPU发送命令:“请将stripe旋转90度”(举例)。所以 CPU 从不绘制像素,而是向 GPU 发送命令。
在 Android 上,您使用 OpenGL 将此类命令发送到 GPU。这使得速度很快,因为图形计算外包给了 GPU。
另请注意,DirectX 是 Microsoft 的 OpenGL 等价物。
我还想补充一点,在执行 CPU 密集型任务时,最好使用 C/C++/Rust 而不是 Java/Kotlin。因为前者直接在 CPU 上运行而后者则没有。这样可以节省电池并且速度更快。请参阅JNI 技巧。