在上一篇《是男人就下100层【第四层】——Crazy贪吃蛇(1)》中我们让贪吃蛇移动了起来,接下来我们来实现让贪吃蛇可以绕着手机屏幕边线移动并且可以改变方向
一、添加状态并修改代码
首先我们来用另外一种方式实现上一版本中的刷新界面,在Crazy贪吃蛇(1)中我们自定义了一个线程每隔1s钟刷新界面,在线程中我们使用了postInvalidate()方法通知主线程重绘界面,我们打开View的源代码看看到底是如何通知主线程的,原代码如下:
public void postInvalidate(int left, int top, int right, int bottom) {
postInvalidateDelayed(0, left, top, right, bottom);
}
/**
* Cause an invalidate to happen on a subsequent cycle through the event
* loop. Waits for the specified amount of time.
*
* @param delayMilliseconds the duration in milliseconds to delay the
* invalidation by
*/
public void postInvalidateDelayed(long delayMilliseconds) {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
if (mAttachInfo != null) {
Message msg = Message.obtain();
msg.what = AttachInfo.INVALIDATE_MSG;
msg.obj = this;
mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
}
}
/**
* Cause an invalidate of the specified area to happen on a subsequent cycle
* through the event loop. Waits for the specified amount of time.
*
* @param delayMilliseconds the duration in milliseconds to delay the
* invalidation by
* @param left The left coordinate of the rectangle to invalidate.
* @param top The top coordinate of the rectangle to invalidate.
* @param right The right coordinate of the rectangle to invalidate.
* @param bottom The bottom coordinate of the rectangle to invalidate.
*/
public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
int right, int bottom) {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
if (mAttachInfo != null) {
final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
info.target = this;
info.left = left;
info.top = top;
info.right = right;
info.bottom = bottom;
final Message msg = Message.obtain();
msg.what = AttachInfo.INVALIDATE_RECT_MSG;
msg.obj = info;
mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
}
}
从上面源代码中我们可以看到最后一句代码mAttachInfo.mHandler.sendMessageDelayed(msg, delayMillisecods),原来也是通过Handler来实现界面刷新的,既然是这样我们就将我们的代码修改如下:
创建一个RefreshHandler类
class RefreshHandler extends Handler{
@Override
public void handleMessage(Message msg) {
MySnake.this.update();
MySnake.this.invalidate();
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
定义了游戏中的四种状态
private enum State{
READ