這兩天,沒事想學習遊戲開發,看了一些資料以後準備開始。爲了未來編碼方便,先寫了一個簡單的遊戲框架方便本身之後作練習用。
若是之後沒有什麼特殊的需求--好比opengl什麼的,會盡可能用這個簡單框架來實現。有優化的地方會在這個裏邊一直更新,也但願有問題的地方但願你們幫忙提一些意見canvas
個人刷新線程基礎類多線程
/** * 個人刷新線程 */ 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(); }
遊戲的顯示界面的基礎類dom
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); } } }
顯示的實現仍是上篇中要顯示的貝塞爾曲線。固然,實現起來比原來代碼簡單多了ide
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; } } }
但願你們多多指正。由於原本有好多線程同步的東西,有問題是不免的。oop