android中的surfaceView是做遊戲的最佳選擇,surfaceView中的重新整理介面是主動進行重新整理 :比如下面這段代碼:
run方法中執行Draw()後,休眠100毫秒
public void run() { while (mIsRunning) { //在這裡加上安全執行緒鎖 synchronized (mSurfaceHolder) { /**拿到當前畫布 然後鎖定**/ mCanvas =mSurfaceHolder.lockCanvas(); Draw(); /**繪製結束後解鎖顯示在螢幕上**/ mSurfaceHolder.unlockCanvasAndPost(mCanvas); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
這樣的代碼看起來很規範,其實在執行draw()方法的時候,所用的時間是不可估計的,即有時候會執行1s, 也可能執行1.1s,這樣的話帶來的問題是顯而易見的。
在貼一段科學的控遊戲制迴圈代碼,每次迴圈遊戲主線程
在Draw()方法前後計算出Draw()方法所消耗的時間,然後在判斷是否達到我們規定的重新整理螢幕時間,下例是以30幀重新整理一次螢幕,如果滿足則繼續下次迴圈如果不滿足使用Thread.yield(); 讓遊戲主線程去等待 並計算當前等待時間直到等待時間滿足30幀為止在繼續下一次迴圈重新整理遊戲螢幕。
這裡說一下Thread.yield(): 與Thread.sleep(long
millis):的區別,Thread.yield():是暫停當前正在執行的線程對象 ,並去執行其他線程。Thread.sleep(long
millis):則是使當前線程暫停參數中所指定的毫秒數然後在繼續執行線程。
/**每30幀重新整理一次螢幕**/ public static final int TIME_IN_FRAME = 30; @Override public void run() { while (mIsRunning) { /**取得更新遊戲之前的時間**/ long startTime = System.currentTimeMillis(); /**在這裡加上安全執行緒鎖**/ synchronized (mSurfaceHolder) { /**拿到當前畫布 然後鎖定**/ mCanvas =mSurfaceHolder.lockCanvas(); Draw(); /**繪製結束後解鎖顯示在螢幕上**/ mSurfaceHolder.unlockCanvasAndPost(mCanvas); } /**取得更新遊戲結束的時間**/ long endTime = System.currentTimeMillis(); /**計算出遊戲一次更新的毫秒數**/ int diffTime = (int)(endTime - startTime); /**確保每次更新時間為30幀**/ while(diffTime <=TIME_IN_FRAME) { diffTime = (int)(System.currentTimeMillis() - startTime); /**線程等待**/ Thread.yield(); } } }