SurfaceView+SurfaceHolder+Thread完成游戏开发

来源:互联网 发布:Ubuntu安装VNC 编辑:程序博客网 时间:2024/06/02 19:29

当前移动端开发有不少框架,如Cocos2d-x等,这些框架其实其原理仍是SurfaceView的操作。只不过是对其进行了优化和重用代码抽取。

所以,明确SurfaceView如何操作就能够更好的使用这些游戏引擎。

 

首先,建立一个GameView类,继承自SurfaceView

 

SurfaceView的线程:

我们可以先看下SurfaceView的介绍:

    // 1Provides a dedicated drawing surface embedded inside of a view

// hierarchy.

// 2One of the purposes of this class is to provide a surface in which a

// secondary thread can render in to the screen.

// If you are going to use it

// this way, you need to be aware of some threading semantics:

//

// All SurfaceView and SurfaceHolder.Callback methods will be called from

// the UI thread.

 

// You must ensure that the drawing thread only touches the underlying

// Surface while it is valid -- between

// SurfaceHolder.Callback.surfaceCreated() and

// SurfaceHolder.Callback.surfaceDestroyed().

SurfaceView中有2种线程,1UI线程,2Render线程。和Activity不同,ActivityUIThread就是主线程,子线程无法操作主线程(即子线程无法更新UI),且无法在UIThread中进行耗时操作(否则报ANR(Application Not Responding错误),但是在SurfaceViewUIThread不负责界面的绘制,而是负责用户的操作,如划屏,点击等。而界面绘制是在RenderThread中完成。(RenderThread需要自定义)。

     // UIThread : 大量的用户的操作

// secondary thread : 界面的绘制

 

SurfaceView的操作:

    对SurfaveView的操作需要SurfaceHolder对象,如设置回调,获取画布(Canvas),画图等。在SurfaceView类中,可以通过getHolder()方法获取SurfaceView对象。

holder = getHolder();

 

 

SurfaceView的生命周期:

SurfaceView中有SurfaceHolder.CallBack()SurfaceView状态变化会调用里面的方法。(即回调方法):

       // The Callback is set with {@link SurfaceHolder#addCallback

// SurfaceHolder.addCallback} method.

@Override

public void surfaceCreated(SurfaceHolder holder) {

}

 

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

}

   

通过SurfaceHolder.addCallBack()方法可以把该回调添加。

 

初始化RenderThread可以在SurfaceCreated中完成。线程销毁也可以在SurfaceDestory中完成。

如下:

public class RenderThread extends Thread{

public boolean isRender = true;

@Override

public void run() {

while (isRender ) {

//进行画图操作

}

}

}

  @Override

public void surfaceCreated(SurfaceHolder holder) {

renderThread = new RenderThread();

renderThread.start();

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

renderThread.isRender = false;

renderThread.interrupt();

}

 

 

SurfaceView中画图:

画图需要的首先就是画布(Canvas),没有画布,无法画图。

我们可以看下源码的类:

 

发现并没有能获取Canvas的方法,但是我们有SurfaceHolder,查看SurfaceHolder的源码发现有lockCanvas()方法能够获取Canvas,果断使用。

 

但,光是这样是不行的,需要操作完Canvas后调用unlockCanvasAndPost()方法。

看一下该方法的介绍:

* Finish editing pixels in the surface.  After this call, the surface's

     * current pixels will be shown on the screen, but its content is lost,

     * in particular there is no guarantee that the content of the Surface

     * will remain unchanged when lockCanvas() is called again.

即完成画图后调用,调用后会把画的图显示在屏幕上,但是不保存内容(Content is lost),当lockCanvas再次调用前,内容保持不变。

也就是说:

lockCanvas()unlockCanvasAndPost()是一个周期。

每个周期会对SurfaceView的显示操作一次,如果想连续动作就需要多次lockCanvasunlockCanvasAndPost()

 

所以RenderThread中的操作如下:

public class RenderThread extends Thread{

public boolean isRender = true;

@Override

public void run() {

while (isRender ) {

//进行画图操作

Canvas canvas = holder.lockCanvas();

canvas.drawBitmap(bitmap, left, top, paint);

holder.unlockCanvasAndPost(canvas);

 

//此处可酌情添加Thread.sleep(),即睡眠时间。

}

}

}

 

由此可知,如果想让游戏更加流畅,需要在Canvas的画图上下功夫!!!

0 0