Android SurfaceHolder处置SurfaceView的画图

Android SurfaceHolder处理SurfaceView的画图

在用SurfaceView进行游戏开发过程中,用到SurfaceHolder来处理它的Canvas上画的效果和动画是必不可少的。用于控制表面,大小,像素等。
Abstract interface to someone holding a display surface. Allows you to control the surface size and format,
edit the pixels in the surface, and monitor changes to the surface. This interface is typically available
through the SurfaceView class.
其中特别要注意以下的几个函数:
abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。
abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。

例子:

// 请参考上一篇文章:android中用SurfaceView做游戏开发


    class DrawThread extends Thread {
        private SurfaceHolder holder;
        private boolean running = true;
        protected DrawThread(SurfaceHolder holder) {this.holder = holder;}
        protected void doStop() { running = false; }
        public void run() {
            Canvas c = null;
            while( running ) {
                c = holder.lockCanvas(null);
                // 锁定整个画布,在内存要求比较高的情况下,建议参数不要为null
                try {
                    synchronized(holder) {
                        bGrid.drawGrid(c);//画游戏中的网格
                        BBoom.drawBooms(c, booms); //画游戏中
                        bFairy.drawFairy(c);//画游戏中的主角
                        // 画的内容是z轴的,后画的会覆盖前面画的。
                    }
                } catch(Exception ex) {}
                finally {
                    holder.unlockCanvasAndPost(c);
                    //更新屏幕显示内容
                }
    
            }
        }
    };

在android中开发游戏,一般来说,或想写一个复杂一点的游戏,是必须用到SurfaceView来开发的。
经过这一阵子对android的学习,我找到了自已在android中游戏开发的误区,不要老想着用Layout和view去实现,不要将某个游戏
中的对象做成一个组件来处理。应该尽量想着在Canvas(画布)中画出游戏戏中的背景、人物、动画等...
SurfaceView提供直接访问一个可画图的界面,可以控制在界面顶部的子视图层。SurfaceView是提供给需要直接画像素而不是使用
窗体部件的应用使用的。Android图形系统中一个重要的概念和线索是surface。View及其子类(如TextView, Button)
要画在surface上。每个surface创建一个Canvas对象(但属性时常改变),用来管理view在surface上的绘图操作,如画点画线。
还要注意的是,使用它的时候,一般都是出现在最顶层的:The view hierarchy will take care of correctly compositing 
with the Surface any siblings of the SurfaceView that would normally appear on top of it.

使用的SurfaceView的时候,一般情况下还要对其进行创建,销毁,改变时的情况进行监视,这就要用到SurfaceHolder.Callback.
class BBatt extends SurfaceView implements SurfaceHolder.Callback {
    public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//看其名知其义,在surface的大小发生改变时激发
    public void surfaceCreated(SurfaceHolder holder){}
//同上,在创建时激发,一般在这里调用画图的线程。
    public void surfaceDestroyed(SurfaceHolder holder) {}
//同上,销毁时激发,一般在这里将画图的线程停止、释放。
}

例子:
public class BBatt extends SurfaceView implements 
                 SurfaceHolder.Callback, OnKeyListener {
             private BFairy bFairy;
             private DrawThread drawThread;
             public BBatt(Context context) {
                 super(context);
                 this.setLayoutParams(
                     new ViewGroup.LayoutParams(
                         Global.battlefieldWidth, Global.battlefieldHeight));
                 this.getHolder().addCallback( this );
                 this.setFocusable( true );
                 this.setOnKeyListener( this );
                 bFairy = new BFairy(this.getContext());
             }
             public void surfaceChanged(SurfaceHolder holder,
                  int format,int width,int height) {
                  drawThread = new DrawThread(holder);
                  drawThread.start();
             }
             public void surfaceDestroyed(SurfaceHolder holder) {
                  if( drawThread != null ) {
                        drawThread.doStop();
                        while (true) try {
                             drawThread.join();
                             break ;
                        } catch(Exception ex) {}
                  }
             }
             public boolean onKey(View view, int keyCode, KeyEvent event) {}
}