這兩天,沒事想學習游戲開發,看了一些資料之后准備開始。為了將來編碼方便,先寫了一個簡單的游戲框架方便自己以后做練習用。
如果以后沒有什么特殊的需求--比如opengl什么的,會盡量用這個簡單框架來實現。有優化的地方會在這個里邊一直更新,也希望有問題的地方希望大家幫忙提一些意見
我的刷新線程基礎類
/** * 我的刷新線程 */ abstract class LoopThread extends Thread{ private boolean DEBUG = true; private Object lock = new Object(); public static final int RUNNING = 1; public static final int PAUSE = 2; public static final int STOP = 0; public int runState = STOP; private WeakReference<CustomSurfaceViewCallBack> callbackRef ; public LoopThread(CustomSurfaceViewCallBack view){ super(); callbackRef = new WeakReference<CustomSurfaceViewCallBack>(view); } @Override public void run() { try { loop(); } catch (InterruptedException e) { this.interrupt(); }finally{ this.runState = STOP; tRelase(); if(DEBUG){ System.out.println(this.getName()+" exit, lock="+lock); } } } private void loop() throws InterruptedException { while(runState!=STOP){ synchronized (lock) { while (runState == RUNNING) { CustomSurfaceViewCallBack callBack = callbackRef.get(); if (callBack == null) { runState = STOP; break; } onLoop(callBack); if (runState == RUNNING) { lock.wait(500); } else { break; } } if(runState==PAUSE){ lock.wait(); }else if(runState==STOP){ lock.notifyAll(); return; } } } } public abstract void onLoop(CustomSurfaceViewCallBack callBack); public void tRelase(){ callbackRef = null; } public void tResume(){ synchronized (lock) { this.runState = LoopThread.RUNNING; lock.notifyAll(); } } public void tPause(){ synchronized (lock) { this.runState = LoopThread.PAUSE; lock.notifyAll(); } } public boolean tStop(){ synchronized (lock) { this.tRelase(); this.runState = LoopThread.STOP; lock.notifyAll(); } while(true){ try { this.join(); return true; } catch (InterruptedException e) { this.interrupt(); } } } }
刷新接口
public interface CustomSurfaceViewCallBack { public abstract boolean processing(); public abstract void doDraw(Canvas canvas); public SurfaceHolder getSurfaceHolder(); }
游戲的顯示界面的基礎類

abstract class CustomSurfaceView extends SurfaceView implements Callback,CustomSurfaceViewCallBack{ private LoopThread dt; private ProcessThread pt; private SurfaceHolder sHolder; public CustomSurfaceView(Context context) { super(context); sHolder = getHolder(); sHolder.addCallback(this); } private boolean singleThread = false; /** * 設置是否用單線程來刷新界面和處理數據。 * 一般來說,為了保證流暢性游戲開發刷新界面的線程和數據處理線程是分開的。如果數據處理耗時,最好分開。如果數據處理耗時較少,可以使用單線程 * @param single */ public void setSingleThread(boolean single){ if(dt!=null){ throw new UnsupportedOperationException("must invoke setSingleThread before surfaceCreated"); } this.singleThread = single; } @Override public void surfaceCreated(SurfaceHolder holder) { start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {} @Override public void surfaceDestroyed(SurfaceHolder holder) { stop(); } /** * 進行界面繪制操作 * @param canvas */ public abstract void doDraw(Canvas canvas); /** * 處理數據 並判斷是否進行界面重繪 * @return */ public abstract boolean processing(); @Override public SurfaceHolder getSurfaceHolder(){ return getHolder(); } public void start(){ if(singleThread){// 如果是單線程的話,初始化一個整合了數據處理和界面刷新一起處理的線程 stop(); dt= new SingleThread(this); dt.runState = LoopThread.RUNNING; dt.start(); return; } if(stop(dt)){ dt = new DrawThread(this); dt.runState = LoopThread.RUNNING; dt.start(); } if(stop(pt)){ pt = new ProcessThread(this); pt.runState = LoopThread.RUNNING; pt.start(); } } /** * 停止一個LoopThread 停止成功返回false * @param t * @return */ private boolean stop(LoopThread t){ if(t==null){ return true; } return t.tStop(); } /** * 游戲停止 */ public void stop(){ stop(dt); stop(pt); } /** * 游戲暫停 */ public void pause(){ if(dt!=null){ dt.tPause(); } if(pt!=null){ pt.tPause(); } } /** * 只可以從游戲暫停狀態讓游戲開始 */ public void resume(){ if(dt!=null){ dt.tResume(); } if(pt!=null){ pt.tPause(); } } /** * 界面繪制線程 * @author cs */ private static class DrawThread extends LoopThread{ public DrawThread(CustomSurfaceView view) { super(view); this.setName("DrawThread--"+this.getId()); } @Override public void onLoop(CustomSurfaceViewCallBack callBack) { drawByCallback(callBack); } } /** * 如果是單線程刷新的話,用到的線程類 * @author cs */ private static class SingleThread extends LoopThread{ public SingleThread(CustomSurfaceView view) { super(view); this.setName("SingleThread--"+this.getId()); } @Override public void onLoop(CustomSurfaceViewCallBack callBack) { callBack.processing(); drawByCallback(callBack); } } /** * 數據處理以及邏輯判斷線程 * @author cs */ private static class ProcessThread extends LoopThread{ public ProcessThread(CustomSurfaceViewCallBack callBack) { super(callBack); this.setName("ProcessThread--"+this.getId()); } @Override public void onLoop(CustomSurfaceViewCallBack callBack) { if(callBack!=null){ callBack.processing(); } } } private static void drawByCallback(CustomSurfaceViewCallBack callBack) { Canvas canvas = null; try { canvas = callBack.getSurfaceHolder().lockCanvas(); if (canvas != null) { callBack.doDraw(canvas); } } catch (Exception e) { e.printStackTrace(); } finally { if (canvas != null) callBack.getSurfaceHolder().unlockCanvasAndPost(canvas); } } }
顯示的實現還是上篇中要顯示的貝塞爾曲線。當然,實現起來比原來代碼簡單多了
public class PathActivity extends Activity { private CustomSurfaceView pathView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); pathView = new PathView(this); pathView.setSingleThread(false); this.setContentView(pathView); } private static class PathView extends CustomSurfaceView{ private int vWidth; private int vHeight; private Paint pPaint; private Path mPath; private float endX; private float endY; private Random random; public PathView(Context context) { super(context); pPaint = new Paint(); pPaint.setAntiAlias(true); pPaint.setColor(0xaf22aa22); pPaint.setStyle(Paint.Style.STROKE); mPath = new Path(); random = new Random(); } private void init(){ vWidth = getWidth(); vHeight = getHeight(); endX = 0.8f*vWidth; endY = 0.8f*vHeight; } @Override public void surfaceCreated(SurfaceHolder holder) { super.surfaceCreated(holder); init(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.surfaceChanged(holder, format, width, height); init(); } @Override public void doDraw(Canvas canvas){ canvas.drawColor(Color.BLACK); canvas.drawPath(mPath, pPaint); } @Override public boolean processing(){ //這里構建貝塞爾曲線 mPath.reset(); mPath.moveTo(50, 50); mPath.quadTo(random.nextInt(vWidth), random.nextInt(vHeight), endX/2, random.nextInt(vHeight)); mPath.quadTo(random.nextInt(vWidth), random.nextInt(vHeight), endX, endY); return true; } } }
希望大家多多指正。因為本來有好多線程同步的東西,有問題是難免的。