zoukankan      html  css  js  c++  java
  • Android SurfaceView 绘图覆盖刷新及“.NET研究”脏矩形刷新方法 狼人:

      SurfaceView在Android中用作游戏开发是最适宜的,本文就将演示游戏开发中常用的两种绘图刷新策略在SurfaceView中的实现方法。

      首先我们来看一下本例需要用到的两个素材图片:

    imageimage  bj.jpg就是一个渐变图,用作背景。

      question.png是一个半透明的图像,我们希望将它放在上面,围绕其圆心不断旋转。

      实现代码如下:

    package SkyD.SurfaceViewTest;
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.os.Bundle;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;

    public class Main extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(
    new MySurfaceView(this));
    }

    // 自定义的SurfaceView子类
    class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    // 背景图
    private Bitmap BackgroundImage;
    // 问号图
    private Bitmap QuestionImage;

    SurfaceHolder Holder;

    public MySurfaceView(Context context) {
    super(context);
    BackgroundImage
    = BitmapFactory.decodeResou上海企业网站制作rce(getResources(),
    R.drawable.bg);
    QuestionImage
    = BitmapFactory.decodeResource(getResources(),
    R.drawable.question);

    Holder
    = this.getHolder();// 获取holder
    Holder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {
    // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    // 启动自定义线程
    new Thread(new MyThread()).start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    }
    // 自定义线程类
    class MyThread implements Runnable {
    @Override
    public void run() {
    Canvas canvas
    = null;
    int rotate = 0;// 旋转角度变量
    while (true) {
    try {
    canvas
    = Holder.lockCanvas();// 获取画布
    Paint mPaint = new Paint();
    // 绘制背景
    canvas.drawBitmap(BackgroundImage, 0, 0, mPaint);
    // 创建矩阵以控制图片旋转和平移
    Matrix m = new Matrix();
    // 设置旋转角度
    m.postRotate((rotate += 48) % 360,
    QuestionImage.getWidth()
    / 2,
    QuestionImage.getHeight()
    / 2);
    // 设置左边距和上边距
    m.postTranslate(47, 47);
    //上海网站建设制问号图
    canvas.drawBitmap(QuestionImage, m, mPaint);
    // 休眠以控制最大帧频为每秒约30帧
    Thread.sleep(33);
    }
    catch (Exception e) {
    }
    finally {
    Holder.unlockCanvasAndPost(canvas);
    // 解锁画布,提交画好的图像
    }
    }
    }
    }
    }
    }

      模拟器中的运行效果:

    image  (注:图中的问号图形是在不断旋转中的)

      这看起来不错,但是有一个问题:我们在代码中设置的帧频最大值是每秒30帧,而实际运行时的帧频根据目测就能看出是到不了30帧的,这是因为程序在每一帧都要对整个画面进行重绘,过多的时间都被用作绘图处理,所以难以达到最大帧频。

      脏矩形刷新

      接下来我们将采取脏矩形刷新的方法来优化性能,所谓脏矩形刷新,意为仅刷新有新变化的部分所在的矩形区域,而其他没用的部分就不去刷新,以此来减少资源浪费。

      我们可以通过在获取Canvas画布时,为其指派一个参数来声明我们需要画布哪个局部,这样就可以只获得这个部分的控制权:

    image  在这里为了便于观察,我将矩形区域设定为问号图形的1/4区域,也就是说在整个画面中我们仅仅更新问号图形的1/4大小那么点区域,其执行效果为:

    SNAGHTML342f602  可以看到,仅有那1/4区域在快速刷新,其他部分都是静止不动的了,现在的刷新帧频差不多已经能达到最大帧频了,我们的优化起作用了:)

      不过别高兴的太早,实际上如果把刷新区域扩大到整个问号图形所在的矩形区域的话,你会发现优化作用变得微乎其微了,还是没法达到最大帧频的,因为更新区域增大了3倍,带来的资源消耗也就大幅增加。

      覆盖刷新

      这种情况下就应当考虑结合覆盖刷新方法再进一步优化了。

      试想一下,我们每次刷新时最大的消耗在哪?

      没错,在背景图绘制上,这个绘制区域非常大,会消耗我们很多资源,但实际上背景图在此例中是从不变化的,也就是说我们浪费了很多资源在无用的地方。

      那么可不可以只绘制一次背景,以后每次都只绘制会动的问号图形呢?

      完全可以,尝试修改一下代码,再前面加一个帧计数器,然后我们仅在第一帧的时候绘制背景:

    image  这样很简单,但是改后直接运行的话你会发现一个奇怪的状况:

    image  问号图案会变得有残影了。

      啊哈,这正是我使用半透明图案做范例的目的,通过这个重影,我们就能看出,覆盖刷新其实就是将每次的新的图形绘制到上一帧去,所以如果图像是半透明的,就要考虑重复叠加导致的问题了,而如果是完全不透明的图形则不会有任何问题。

      背景会在背景图和黑色背景之间来回闪。

      这个问题其实是源于SurfaceView的双缓冲机制,我理解就是它会缓冲前两帧的图像交替传递给后面的帧用作覆盖,这样由于我们仅在第一帧绘制了背景,第二帧就是无背景状态了,且通过双缓冲机制一直保持下来,解决办法就是改为在前两帧都进行背景绘制:

    image  现在就没有问题了(如果换成个不透明的图形的话就真没问题了):

    image  现在虽然还是达不到最大帧频,但是也算不错啦,在真机上跑的会更快些,接近最大帧频了。

      结语

      我这也是刚接触Android开发,分享这点心得出来,有写的不对的欢迎指点一二^^

    声明:此博有部分内容为转载,版权归原作者所有~
  • 相关阅读:
    【题解】【BT】【Leetcode】Populating Next Right Pointers in Each Node
    【题解】【BT】【Leetcode】Binary Tree Level Order Traversal
    【题解】【BST】【Leetcode】Unique Binary Search Trees
    【题解】【矩阵】【回溯】【Leetcode】Rotate Image
    【题解】【排列组合】【素数】【Leetcode】Unique Paths
    【题解】【矩阵】【回溯】【Leetcode】Unique Paths II
    【题解】【BST】【Leetcode】Validate Binary Search Tree
    【题解】【BST】【Leetcode】Convert Sorted Array to Binary Search Tree
    第 10 章 判断用户是否登录
    第 8 章 动态管理资源结合自定义登录页面
  • 原文地址:https://www.cnblogs.com/waw/p/2219556.html
Copyright © 2011-2022 走看看