SurfaceView 游戏线程上的 drawBitmap 性能低下 (android)

drawBitmap low performance on SurfaceView game thread (android)

我正在 SurfaceView 上绘制一组图像 canvas。 doDraw 在获取 surfaceHolder 后由游戏循环线程调用。问题是当在 canvas 上绘制的图像数量很大时,每秒帧数 (FPS) 确实很低。这是因为 drawBitmap 很慢。

测试设置

clusters arraylist 有 400 个小图像 (cluster.Picture)。时间差是 运行 drawBitmap 循环的测量参数。为了进行比较,我用 drawRect 替换了 drawBitmap,并且还注释掉了 drawBitmap,使循环体为空。 用于测试的设备 https://www.optus.com.au/shop/prepaidmobile/lg/leon

测试结果(毫秒)

  1. drawBitmap 400 循环 - 平均值:25.5,最小值:14,最大值:37
  2. drawRect 400 循环 - 平均值:8.6,最小值:5,最大值:21
  3. 无 400 循环 - 平均值:1.3,最小值:0,最大值:10

以上时间只测了部分逻辑。整个游戏循环需要将近 40 毫秒。这意味着 FPS 真的很低。即使是 100 次循环,仅绘制位图也需要 18 毫秒。

我尝试设置 getHolder().setFormat(PixelFormat.RGBA_8888)、setFixedSize(screenSize.x , screenSize.y) 和 zorder 以及将位图配置设置为 RGBA_8888.此外,我尝试使用游戏线程的 setPriority 设置高优先级。

我不确定我还能做什么。如何提高游戏循环和 FPS 的性能。

    public List<PCluster> clusters = new ArrayList<PCluster>();

    public void doDraw(Canvas canvas) {

    try {
        if (canvas == null) {
            return;
        }
        super.draw(canvas);

        canvas.drawColor(backColor);
        if (waitTillLoad) {
            return;
        }

    } catch (Exception ex) {
    }
    final int savedState = canvas.save();
    try {

        minX = (int) (((viewWidth / mScaleFactor) - Gen.screenSizeWidth) / 2) * Utils.VIEW_SIZE;
        minY = (int) (((viewHeight / mScaleFactor) - Gen.screenSizeHeight) / 2) * Utils.VIEW_SIZE;

        if (mPosX > maxX) {
            mPosX = maxX;
        }
        if (mPosX < minX) {
            mPosX = minX;
        }
        if (mPosY > maxY) {
            mPosY = maxY;
        }
        if (mPosY < minY) {
            mPosY = minY;
        }


        canvas.scale(mScaleFactor, mScaleFactor);
        canvas.translate(mPosX, mPosY);

        long startTime = System.currentTimeMillis();
        if (!showBackground) {

            for (PCluster cluster : clusters) {
                if (cluster.isVisible) {
                    canvas.drawBitmap(cluster.Picture, cluster.BoardLocation.left,
                            cluster.BoardLocation.top, null);
                }
            }
            Log.d("myApp", "   " + (System.currentTimeMillis() - startTime));
        }

    } catch (Exception ex) {
    } finally {
        canvas.restoreToCount(savedState);
    }
}

我能够使用 PorterDuff SRC_OVER 绘制对象来提高性能。这可能是因为透明图像相互重叠绘制时计算较少。还要确保为绘画添加抖动和抗锯齿。

canvasPaint = new Paint();
canvasPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER )); 

canvas.drawBitmap(cluster.Picture, cluster.BoardLocation.left,
                            cluster.BoardLocation.top, canvasPaint );