在上一篇《是男人就下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 windowif (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 windowif (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{@Overridepublic 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{READY,    //就绪PAUSE,    //暂停RUNNING,  //执行LOSE      //失败}
    private void update(){if(currentState == State.RUNNING){move();mRefreshHandler.sleep(1000);}}
我们再来看看上个版本号中使蛇移动的核心代码:
        case LEFT:  /*for(int i=0; i<boxs.size(); i++){  box = boxs.get(i);  box.setX(box.getX() - boxSize);  } */boxs.add(0, new Box(boxs.get(0).getX() - boxSize, 0));boxs.remove(boxs.size() - 1);break;  case RIGHT:  /* for(int i=0; i<boxs.size(); i++){  box = boxs.get(i);  box.setX(box.getX() + boxSize);  }  */boxs.add(new Box(boxs.get(boxs.size() - 1).getX() + boxSize, 0));boxs.remove(0);break; 

我们不用遍历每个方块来实现蛇的移动,我们仅仅须要去改变蛇首和蛇未就可以实现。

改动后的MySnake.java文件

package com.example.crazysnake;  import java.util.ArrayList;
import java.util.List;  import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/*** CSDN博客:http://blog.csdn.net/dawanganban* @author 阳光小强*/
public class MySnake extends View {  private Paint paint;  private RectF rect;  private int boxSize = 30;  // private SnakeThread snakeThread;  private List<Box> boxs = new ArrayList<Box>(); private static final int[] colors = {  Color.RED,  Color.BLUE,   Color.GREEN,  Color.YELLOW  };  private enum Derectory{  LEFT,  RIGHT,  TOP,  BOTTOM;  }  private enum State{READY,    //就绪PAUSE,    //暂停RUNNING,  //执行LOSE      //失败}private Derectory currentDerect = Derectory.RIGHT;  private State currentState = State.PAUSE;private RefreshHandler mRefreshHandler = new RefreshHandler();class RefreshHandler extends Handler{@Overridepublic void handleMessage(Message msg) {MySnake.this.update();MySnake.this.invalidate();}public void sleep(long delayMillis) {this.removeMessages(0);sendMessageDelayed(obtainMessage(0), delayMillis);}}public MySnake(Context context, AttributeSet attrs) {  super(context, attrs);  paint = new Paint();  rect = new RectF();  initData();  //startThread();  }  /*    public void startThread(){  if(snakeThread == null){  snakeThread = new SnakeThread();  snakeThread.start();  }  } */ private void update(){if(currentState == State.RUNNING){move();mRefreshHandler.sleep(1000);}}private void initData(){  Box box;  for(int i=0; i<10; i++){  box = new Box(i*boxSize, 0);  boxs.add(box);  }  }  private float mDownX;  private float mDownY;  @Override  public boolean onTouchEvent(MotionEvent event) {System.out.println("onTouch");  switch (event.getAction()) {  case MotionEvent.ACTION_DOWN:  mDownX = event.getX();  mDownY = event.getY();  break;  case MotionEvent.ACTION_UP:  float disX = event.getX() - mDownX;  float disY = event.getY() - mDownY;  System.out.println("disX = " + disX);  System.out.println("dixY = " + disY);  if(Math.abs(disX) > Math.abs(disY)){  if(disX > 0){  if(currentState != State.RUNNING){currentState = State.RUNNING;update();}currentDerect = Derectory.RIGHT;  }else{  currentDerect = Derectory.LEFT;  }  }else{  if(disY > 0){  currentDerect = Derectory.BOTTOM;  }else{  currentDerect = Derectory.TOP;  }  }  break;  }  return true;  }  /*    private class SnakeThread extends Thread{  private boolean stoped = false;  @Override  public void run() {  while(!stoped){  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  e.printStackTrace();  }  move();  postInvalidate();  }  }  }  */private void move(){  Box box;  //推断边界条件if(boxs.get(0).getX() - boxSize < 0) {  currentDerect = Derectory.RIGHT;  }  if(boxs.get(boxs.size() - 1).getX() + 2 * boxSize > getWidth()){  currentDerect = Derectory.LEFT;  }  switch (currentDerect) {  case LEFT:  /*for(int i=0; i<boxs.size(); i++){  box = boxs.get(i);  box.setX(box.getX() - boxSize);  } */boxs.add(0, new Box(boxs.get(0).getX() - boxSize, 0));boxs.remove(boxs.size() - 1);break;  case RIGHT:  /* for(int i=0; i<boxs.size(); i++){  box = boxs.get(i);  box.setX(box.getX() + boxSize);  }  */boxs.add(new Box(boxs.get(boxs.size() - 1).getX() + boxSize, 0));boxs.remove(0);break;  case TOP:  break;  case BOTTOM:  break;  }  }  @Override  protected void onDraw(Canvas canvas) {  super.onDraw(canvas);  for(int i=0; i<boxs.size(); i++){  paint.setColor(colors[i % colors.length]);  rect.set(boxs.get(i).getX(), boxs.get(i).getY(), boxs.get(i).getX() + boxSize, boxSize);  canvas.drawRect(rect, paint);  }  }
}

二、实现绕手机边界移动的贪吃蛇

先看看实现的效果:
实现代码例如以下:
package com.example.crazysnake;  import java.util.ArrayList;
import java.util.List;  import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/*** CSDN博客:http://blog.csdn.net/dawanganban* @author 阳光小强*/
public class MySnake extends View {  private Paint paint; private Paint textPaint;private RectF rect;  private static int boxSize = 40;  private static int xMaxBoxCount;  //x轴方向最多的box数量private static int yMaxBoxCount;  //y轴方向最多的box数量private List<Box> boxs = new ArrayList<Box>(); private static final int[] colors = {  Color.RED,  Color.BLUE,   Color.GRAY,  Color.YELLOW  };  private enum Derectory{  LEFT,  RIGHT,  TOP,  BOTTOM;  }  private enum State{READY,    //就绪PAUSE,    //暂停RUNNING,  //执行LOSE      //失败}private Derectory currentDerect = Derectory.LEFT;  private State currentState = State.READY;private RefreshHandler mRefreshHandler = new RefreshHandler();class RefreshHandler extends Handler{@Overridepublic void handleMessage(Message msg) {MySnake.this.update();MySnake.this.invalidate();}public void sleep(long delayMillis) {this.removeMessages(0);sendMessageDelayed(obtainMessage(0), delayMillis);}}public MySnake(Context context, AttributeSet attrs) {  super(context, attrs);  paint = new Paint(); textPaint = new Paint();textPaint.setColor(Color.RED);textPaint.setTextSize(80);rect = new RectF();  initData();   }  private void update(){if(currentState == State.RUNNING){move();mRefreshHandler.sleep(150);}}private void initData(){  Box box;  for(int i=5; i<10; i++){  box = new Box(i, 0);  boxs.add(box);  }  }  @Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);xMaxBoxCount = (int) Math.floor(w / boxSize);yMaxBoxCount = (int) Math.floor(h / boxSize);}private float mDownX;  private float mDownY;  @Override  public boolean onTouchEvent(MotionEvent event) {System.out.println("onTouch");  switch (event.getAction()) {  case MotionEvent.ACTION_DOWN:  mDownX = event.getX();  mDownY = event.getY();  break;  case MotionEvent.ACTION_UP:  float disX = event.getX() - mDownX;  float disY = event.getY() - mDownY;  System.out.println("disX = " + disX);  System.out.println("dixY = " + disY);  if(Math.abs(disX) > Math.abs(disY)){  if(disX > 0){  //  currentDerect = Derectory.RIGHT;  }else{  if(currentState != State.RUNNING){currentState = State.RUNNING;currentDerect = Derectory.LEFT;  update();}}  }else{  if(disY > 0){  //  currentDerect = Derectory.BOTTOM;  }else{  //  currentDerect = Derectory.TOP;  }  }  break;  }  return true;  }  private void move(){  Box box;  if(currentDerect == Derectory.LEFT && boxs.get(0).getX() <= 0){currentDerect = Derectory.BOTTOM;}if(currentDerect == Derectory.BOTTOM && boxs.get(0).getY() >= yMaxBoxCount -1){currentDerect = Derectory.RIGHT;}if(currentDerect == Derectory.RIGHT && boxs.get(0).getX() >= xMaxBoxCount - 1){currentDerect = Derectory.TOP;}if(currentDerect == Derectory.TOP && boxs.get(0).getY() <= 0){currentDerect = Derectory.LEFT;}switch (currentDerect) {case LEFT:  boxs.add(0, new Box(boxs.get(0).getX() - 1, boxs.get(0).getY()));boxs.remove(boxs.size() - 1);break;  case RIGHT:  boxs.add(0, new Box(boxs.get(0).getX() + 1, boxs.get(0).getY()));boxs.remove(boxs.size() - 1);break;  case TOP:  boxs.add(0, new Box(boxs.get(0).getX(), boxs.get(0).getY() - 1));boxs.remove(boxs.size() - 1);  break;  case BOTTOM:  boxs.add(0, new Box(boxs.get(0).getX(), boxs.get(0).getY() + 1));boxs.remove(boxs.size() - 1);break;  }  }  @Override  protected void onDraw(Canvas canvas) {  super.onDraw(canvas);  for(int i=0; i<boxs.size(); i++){  paint.setColor(colors[i % colors.length]);  rect.set(boxs.get(i).getX() * boxSize, boxs.get(i).getY() * boxSize, (boxs.get(i).getX() + 1) * boxSize, (boxs.get(i).getY() + 1) * boxSize);  canvas.drawRect(rect, paint);  } if(currentState == State.READY){canvas.drawText("请向左滑动", (xMaxBoxCount * boxSize - textPaint.measureText("请向左滑动")) / 2,xMaxBoxCount * boxSize / 2, textPaint);}}
}

源代码下载说明:前一个版本号在GitHub上,这一版我将该项目上传到了CSDN的CODE上面,能够使用SVN或Git下载
CODE源代码下载地址:https://code.csdn.net/lxq_xsyu/crazysnake

CSDN下载地址:http://download.csdn.net/detail/lxq_xsyu/7629435

是男人就下100层【第四层】——Crazy贪吃蛇(2)相关推荐

  1. 是男人就下100层【第四层】——Crazy贪吃蛇(3)

    上一篇< 是男人就下100层[第四层]--Crazy贪吃蛇(2)>实现了贪吃蛇绕着屏幕四周移动,这一篇我们来完成贪吃蛇的所有功能. 一.随机产生苹果 private void addApp ...

  2. 是男人就下100层【第五层】——2048游戏从源代码到公布市场

    上一篇<是男人就下100层[第五层]--换肤版2048游戏>中阳光小强对2048游戏用自己的方式进行了实现,并分享了核心源码,这一篇阳光小强打算将该项目的全部源码公开并结合这个实例在这篇文 ...

  3. 是男人就下100层【第一层】——高仿微信界面(4)

    上一篇<是男人就下100层[第一层]--高仿微信界面(3)>中我们完成了登录,这一篇看完成登录后的一个短暂加载和引导界面. 加载界面: <RelativeLayout xmlns:a ...

  4. 《是男人就下100层》真的有隐藏剧情!B站up主数月破解,原作者点赞致谢

    边策 杨净 发自 凹非寺 量子位 报道 | 公众号 QbitAI <是男人就下100层>,曾经风靡一代的flash小游戏.炙手可热的休闲游戏之最. 它让多少人没日没夜地想去尝试" ...

  5. Unity经典游戏教程之:是男人就下100层

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  6. 是男人就下100层【第五层】——2048游戏从源码到发布市场

    上一篇<是男人就下100层[第五层]--换肤版2048游戏>中阳光小强对2048游戏用自己的方式进行了实现,并分享了核心源码,这一篇阳光小强打算将该项目的所有源代码公开并结合这个实例在这篇 ...

  7. cocos2d-x 是男人就下100层 附源码

    1.效果图: 玩法: 一个不断下降的小人,点击屏幕的left或者right控制小人的移动方向,尽可能生存久些.为什么要搞这个游戏呢?因为在2012年的8月份,我完成它的android版本,见<自 ...

  8. OpenGL2D小游戏——是男人就下100层

    2019独角兽企业重金招聘Python工程师标准>>> 是男人就下100层想必大家一定都玩过,在这里给大家简单介绍一下游戏规则. 游戏规则: 游戏人物从屏幕上方按一定速率下落,同时台 ...

  9. 是男人就下100层【第一层】——高仿微信界面(8)

    上一篇<是男人就下100层[第一层]--高仿微信界面(7)>中我们实现了下弹式菜单,这一篇我们来看看如何实现微信中的摇一摇功能. 首先我们来布局我们的摇一摇界面 布局文件如下: <? ...

最新文章

  1. javascript callback函数的理解与使用
  2. loadrunner 分用户日志
  3. matlab 取43阶上部分,求教关于matlab四阶累积量函数里变量的意义。
  4. [转载] AUML——Schedules and Events
  5. 项目合作| 视频监控解决隧道洗车线的安全问题
  6. 关于.dll' could not be found 的问题以及解决方案
  7. 中国电信物联网平台入门学习笔记3: 电信开发者平台使用
  8. 对因果报应和轮回的态度
  9. 华为网络安全论述题解析(1)
  10. 网络性能衡量的指标有哪些?
  11. 小程序Progress组件介绍
  12. Maya vray 3S皮肤材质球设置与材质节点连接
  13. Qt下使用vs编译的库文件
  14. 《TeeRex (Sec‘20)》笔记
  15. Linux安装CentOS系统
  16. kong mysql_konga 安装
  17. 搭建简单的Netty开发环境
  18. 想了3年,实现只用了3个月
  19. Java定时任务汇总
  20. 36.深度解密三十六:网络舆情监测之另类“免费监测”方法详解

热门文章

  1. 【Qt】在QtCreator中编译log4cplus
  2. 【C++】C++11 STL算法(六):最小/最大操作(Minimum/maximum operations)、比较运算(Comparison operations)
  3. 【Qt】Qt项目常用代码总结
  4. java图书分析echarts_Echarts后台Java解析
  5. 【js】创建数组的三种方法
  6. ios如何实现静音模式下声音仍然可以外放
  7. 1小时学会:最简单的iOS直播推流(四)如何使用GPUImage,如何美颜
  8. 微信小程序实现滑动翻页效果源码附效果图
  9. iOS 计算两个日期之间的差值
  10. 【iOS】通过NSURLProtocol提高Web加载速度