標籤:des android style blog color os 使用 io for
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初探