是男人就下100層【第四層】——Crazy貪吃蛇(2)

來源:互聯網
上載者:User

標籤:android   貪吃蛇   

在上一篇《是男人就下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{    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{    @Override    public 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{    @Override    public 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);          }      }          @Override    protected 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/crazysnakeCSDN:http://download.csdn.net/detail/lxq_xsyu/7629435

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.