LunarLander and Snake 游戏更新线程总结
snake:是通过send和receive MSG方法来实现视图的跟新。invalidate()
sudokuv:是也是通过invalidate跟新视图。由于没有自更新。所以视图变化发生在按键事件
jetboy:类似lunarlander
LunarLander:是通过线程在RUN方法中while(TRUE)中一直执行dodraw方法。其中它需要取得屏幕的canvas
1.extends view。这个方法所有的绘制都在onDraw()函数里进行,通过调用invalidate()通知系统调用onDraw()重绘屏幕,但是如果是在非UI线程中请求重绘就不一样了,具体怎么做大家自己去看看相关的东西。我没有看过,因为一般游戏开发我们会选择下一种方法。
2.extends SurfaceView,这是游戏开发最常用的方式,应该说如果你的游戏需要不停的更新图像,比如有帧动画的播放等等,那么就采用这种方式吧。
surfaceview的方式下你需要 implements SurfaceHolder.Callback
class SurfaceViewCore extends SurfaceView implements SurfaceHolder.Callback
LunarLander
class LunarView extends SurfaceView implements SurfaceHolder.Callback { public LunarView(Context context, AttributeSet attrs) { super(context, attrs); // register our interest in hearing about changes to our surface SurfaceHolder holder = getHolder(); holder.addCallback(this); // create thread only; it's started in surfaceCreated() thread = new LunarThread(holder, context, new Handler() { @Override public void handleMessage(Message m) { mStatusText.setVisibility(m.getData().getInt("viz")); mStatusText.setText(m.getData().getString("text")); } }); setFocusable(true); // make sure we get key events } @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) thread.pause(); } public void surfaceCreated(SurfaceHolder holder) { // start the thread here so that we don't busy-wait in run() // waiting for the surface to be created thread.setRunning(true); thread.start(); } public void surfaceDestroyed(SurfaceHolder holder) { // we have to tell thread to shut down & wait for it to finish, or else // it might touch the Surface after we return and explode boolean retry = true; thread.setRunning(false); while (retry) { try { thread.join(); retry = false; } catch (InterruptedException e) { } } } class LunarThread extends Thread { public LunarThread(SurfaceHolder surfaceHolder, Context context, Handler handler) { // get handles to some important objects mSurfaceHolder = surfaceHolder; mHandler = handler; mContext = context; } public void run() { while (mRun) { Canvas c = null; try { c = mSurfaceHolder.lockCanvas(null); synchronized (mSurfaceHolder) { if (mMode == STATE_RUNNING) updatePhysics(); doDraw(c); } } finally { // do this in a finally so that if an exception is thrown // during the above, we don't leave the Surface in an // inconsistent state if (c != null) { mSurfaceHolder.unlockCanvasAndPost(c); } } } } public void setState(int mode, CharSequence message) { synchronized (mSurfaceHolder) { mMode = mode; if (mMode == STATE_RUNNING) { Message msg = mHandler.obtainMessage(); Bundle b = new Bundle(); b.putString("text", ""); b.putInt("viz", View.INVISIBLE); msg.setData(b); mHandler.sendMessage(msg); } else { if (message != null) { str = message + "\n" + str; } if (mMode == STATE_LOSE) mWinsInARow = 0; Message msg = mHandler.obtainMessage(); Bundle b = new Bundle(); b.putString("text", str.toString()); b.putInt("viz", View.VISIBLE); msg.setData(b); mHandler.sendMessage(msg); } } } private void doDraw(Canvas canvas) { } }}
public class SnakeView extends TileView { private static final Random RNG = new Random(); private RefreshHandler mRedrawHandler = new RefreshHandler(); class RefreshHandler extends Handler { @Override public void handleMessage(Message msg) { SnakeView.this.update(); SnakeView.this.invalidate(); } public void sleep(long delayMillis) { this.removeMessages(0); sendMessageDelayed(obtainMessage(0), delayMillis); } }; public SnakeView(Context context, AttributeSet attrs) { super(context, attrs); initSnakeView(); } public SnakeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initSnakeView(); } private void initSnakeView() { setFocusable(true); } private void initNewGame() { } public void update() { mRedrawHandler.sleep(mMoveDelay); } } }