首页 > 代码库 > Android 游戏开发(二)SurfaceView初探

Android 游戏开发(二)SurfaceView初探

SurfaceView游戏框架在游戏开发当中有举足轻重的地位。
SurfaceHolder类是用来控制SurfaceView的大小、格式,并且主要用于监听Surface的状态。
SurfaceView好像就是一块内存数据里面记录着数据,更改数据而是由SurfaceHolder来控制,使用SurfaceHolder的lockCanvas()函数来获取SurfaceView的Canvas对象。然后在Canvas上绘制内容来修改SurfaceView中的数据。

 

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;public class MySurfaceView extends SurfaceView implements Callback {    //该类主要是用来监听SurfaceView的状态    private SurfaceHolder holder;    private Paint paint;        public MySurfaceView(Context context) {        super(context);        holder = this.getHolder();        //为Surface添加监听状态        holder.addCallback(this);        //实例一只画笔        paint = new Paint();        //将画笔设置为白色        paint.setColor(Color.WHITE);    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        myDraw();    }    @Override    public void surfaceDestroyed(SurfaceHolder arg0) {    }    private void myDraw() {        //lockCanvas不仅仅是得到Canvas,并且对Canvas加锁        //防止在绘制过程中遭到破坏        Canvas mCanvas = holder.lockCanvas();        mCanvas.drawText("Game", 50, 10, paint);        holder.unlockCanvasAndPost(mCanvas);    }        @Override    protected void onDraw(Canvas canvas) {        canvas.drawText("Game", 50, 50, paint);        super.onDraw(canvas);    }}

 

在SurfaceView中重载的onDraw()方法并不会执行,更加能够说明了SurfaceView是通过SurfaceHolder来修改数据的,所以SurfaceView即使重写了onDraw()方法也不会执行到。接下来重复上一次View的操作,重写onTouchEvent()方法。

@Overridepublic boolean onTouchEvent(MotionEvent event) {    posX = (int) event.getX();    posY = (int) event.getY();    myDraw();    return true;}

 

发现重写onTouchEvent()方法后,屏幕绘制变得乱七八糟。跟上一次重写后的效果完全不一样。其主要原因是画布没有刷新,将每次绘制的文本全部都显示了出来。解决方法就是对画布进行“刷屏”。

private void myDraw() {    Canvas mCanvas = holder.lockCanvas();    //就是在重绘之前用一张背景,将原来的覆盖掉    paint.setColor(Color.BLACK);    mCanvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint);    paint.setColor(Color.WHITE);    mCanvas.drawText("Game", posX, posY, paint);    holder.unlockCanvasAndPost(mCanvas);}


SurfaceView视图添加线程
在游戏中,基本上不会等用户触发了某个事件才去重绘画布,而是一个较短的固定周期去重绘画布;比如动态的花花草草,流水等场景,这些游戏元素并不会跟玩家进行交互。但是这些元素都是动态的。所以游戏开发中,都会有一个线程不停的去重新绘制。

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;public class MySurfaceView extends SurfaceView implements Callback , Runnable{    //该类主要是用来监听SurfaceView的状态    private SurfaceHolder holder;    private Paint paint;    private int posX = 100;    private int posY = 100;    private int flag;    private Canvas canvas;    private int screenW, screenH;        public MySurfaceView(Context context) {        super(context);        holder = this.getHolder();        //为Surface添加监听状态        holder.addCallback(this);        //实例一只画笔        paint = new Paint();            //将画笔设置为白色        paint.setColor(Color.WHITE);        paint.setTextSize(50f);        //设置焦点        setFocusable(true);    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        screenH = this.getHeight();        screenW = this.getWidth();        flag = 1;        new Thread(this).start();    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        flag = 0;    }    private void myDraw() {        try {            canvas = holder.lockCanvas();            if(canvas!=null){                //就是在重绘之前用一张背景,将原来的覆盖掉                paint.setColor(Color.BLACK);                canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint);                paint.setColor(Color.WHITE);                canvas.drawText("Game", posX, posY, paint);            }        } catch (Exception e) {        }finally{            if(canvas!=null){                holder.unlockCanvasAndPost(canvas);            }        }    }        @Override    public boolean onTouchEvent(MotionEvent event) {        posX = (int) event.getX();        posY = (int) event.getY();        myDraw();        return true;    }    private void logic(){}//游戏逻辑    @Override    public void run() {        while(flag==1){            long start = System.currentTimeMillis();            myDraw();            logic();            long end = System.currentTimeMillis();            try {                //保证重绘的最小周期是50                if(end - start < 50){                    Thread.sleep(50 - (end -start));                }            } catch (InterruptedException e) {            }        }    }}

 

一般游戏的刷新时间是50-100毫秒,也就是每秒10-20帧左右。

最后感谢百度、感谢《游戏编程之从0开始》。

 

Android 游戏开发(二)SurfaceView初探