Android中贪吃蛇游戏的学习(三)

Android中贪吃蛇游戏的学习(三)

文章分类:移动开发

视图VIew的类的Snake的,主要关注的学习的类。

Java代码 复制代码
  1. package com.easyway.dev.android.snake;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Random;   
  5.   
  6. import android.content.Context;   
  7. import android.content.res.Resources;   
  8. import android.os.Bundle;   
  9. import android.os.Handler;   
  10. import android.os.Message;   
  11. import android.util.AttributeSet;   
  12. import android.util.Log;   
  13. import android.view.KeyEvent;   
  14. import android.view.View;   
  15. import android.widget.TextView;   
  16.   
  17. /**  
  18.  * View类是Android的一个超类,这个类几乎包含了所有的屏幕类型。但它们之间有一些不同。每一个view  
  19.  * 都有一个用于绘画的画布。这个画布可以用来进行任意扩展。  
  20.  *   
  21.  * 一个项目的R.java文件是一个定义所有资源的索引文件。 使用这个类就像使用一种速记方式来引用你项  
  22.  * 目中包含的资源。这个有点特别的强大像对于Eclipse这类IDE的代码编译特性,因为它使你快速的,互动  
  23.  * 式的定位你正在寻找的特定引用。  
  24.  *   
  25.  * 到目前需要注意的重要事情是叫做”layout”的内部类和他的成员变量”main”, 插件会通知你添加一个新  
  26.  * 的XML布局文件,然后从新产生这个R.java文件,比如你添加了新的资源到你的项目,你将会看到R.java  
  27.  * 也相应的改变了。放在你的项目目录的res/ 文件夹下。 “res”是”resources”的缩写,它是存放所有非  
  28.  * 代码资源的文件夹,包含象图片,本地化字符串和XML布局文件。  
  29.  *   
  30.  *   
  31.  * SnakeView: implementation of a simple game of Snake  
  32.  * 创建的view中一般要传入一个Context的实例,Context 可以控制系统的调用,它提供了诸如资源解析  
  33.  * ,访问数据库等。Activty类继承自Context类。   
  34.  *   
  35.  * 视图也可以被嵌套,但和J2ME不同,我们可以将定制的视图和Android团队发布的Widgets一起使用。  
  36.  * 在J2ME中,开发人员被迫选择GameCanvas和J2ME应用程序画布。这就意味着如果我们想要一个定制  
  37.  * 的效果,就必须在GameCanvas上重新设计我们所有的widget。Android还不仅仅是这些,视图类型  
  38.  * 也可以混合使用。Android还带了一个widget库,这个类库包括了滚动条,文本实体,进度条以及其  
  39.  * 他很多控件。这些标准的widget可以被重载或被按着我们的习惯定制。  
  40.  *   
  41.  */  
  42. public class SnakeView extends TileView {   
  43.   
  44.     private static final String TAG = "SnakeView";   
  45.   
  46.     /**  
  47.      * Current mode of application: READY to run, RUNNING, or you have already  
  48.      * lost. static final ints are used instead of an enum for performance  
  49.      * reasons.  
  50.      */  
  51.     private int mMode = READY;   
  52.     public static final int PAUSE = 0;   
  53.     public static final int READY = 1;   
  54.     public static final int RUNNING = 2;   
  55.     public static final int LOSE = 3;   
  56.   
  57.     /**  
  58.      * 设置方向  
  59.      * Current direction the snake is headed.  
  60.      */  
  61.     private int mDirection = NORTH;   
  62.     private int mNextDirection = NORTH;   
  63.     private static final int NORTH = 1;   
  64.     private static final int SOUTH = 2;   
  65.     private static final int EAST = 3;   
  66.     private static final int WEST = 4;   
  67.   
  68.     /**  
  69.      * Labels for the drawables that will be loaded into the TileView class  
  70.      */  
  71.     private static final int RED_STAR = 1;   
  72.     private static final int YELLOW_STAR = 2;   
  73.     private static final int GREEN_STAR = 3;   
  74.   
  75.     /**  
  76.      * mScore: used to track the number of apples captured mMoveDelay: number of  
  77.      * milliseconds between snake movements. This will decrease as apples are  
  78.      * captured.  
  79.      */  
  80.     private long mScore = 0;   
  81.     private long mMoveDelay = 600;   
  82.     /**  
  83.      * mLastMove: tracks the absolute time when the snake last moved, and is used  
  84.      * to determine if a move should be made based on mMoveDelay.  
  85.      */  
  86.     private long mLastMove;   
  87.        
  88.     /**  
  89.      * mStatusText: text shows to the user in some run states  
  90.      */  
  91.     private TextView mStatusText;   
  92.   
  93.     /**  
  94.      * 用于存储贪吃蛇中,苹果和蛇的点阵的坐标的信息的集合  
  95.      * mSnakeTrail: a list of Coordinates that make up the snake's body  
  96.      * mAppleList: the secret location of the juicy apples the snake craves.  
  97.      */  
  98.     private ArrayList<Coordinate> mSnakeTrail = new ArrayList<Coordinate>();   
  99.     private ArrayList<Coordinate> mAppleList = new ArrayList<Coordinate>();   
  100.   
  101.     /**  
  102.      * 为创建苹果坐标使用随机对象  
  103.      * Everyone needs a little randomness in their life  
  104.      */  
  105.     private static final Random RNG = new Random();   
  106.   
  107.     /**  
  108.      * 刷新界面处理器  
  109.      * Create a simple handler that we can use to cause animation to happen.  We  
  110.      * set ourselves as a target and we can use the sleep()  
  111.      * function to cause an update/invalidate to occur at a later date.  
  112.      */  
  113.     private RefreshHandler mRedrawHandler = new RefreshHandler();   
  114.     /**  
  115.      * 实现刷新的功能:  
  116.      *在J2ME中,刷新都是在canvas中通过调用线程结合repaint()来刷新, 他们使线程不断去循环,  
  117.      *去调用canvas, 笔者在android 入门时也曾经想用J2ME的模式用在android 中,结果报异常了,   
  118.      *为什么呢? 很多人认为Dalvik虚拟机是一个Java虚拟机,因为Android的编程语言恰恰就是Java语言。  
  119.      *但是这种说法并不准确,因为Dalvik虚拟机并不是按照Java虚拟机的规范来实现的,两者并不兼容;  
  120.      *同时还要两个明显的不同: Java虚拟机运行的是Java字节码,而Dalvik虚拟机运行的则是其专有的  
  121.      *文件格式DEX(Dalvik Executable)。所以在以前JAVA 里面能使用的模式, 可能在android   
  122.      *里面用不起来 。在自带的例子里面他是通过消息的机制来刷新的。而在android的消定义比较广泛,  
  123.      * 比如,手机的暂停, 启动, 来电话、短信,键盘按下,弹起都是一个消息。总的来说, 事件就是消息;  
  124.      * 只要继承Handler类就可以对消息进行控制,或者处理, 根据具体情况进行具体处理:   
  125.      *   
  126.      * @author Administrator  
  127.      * @date 2010-5-24  
  128.      * @version 1.0  
  129.      * @since JDK6.0  
  130.      */  
  131.     class RefreshHandler extends Handler {   
  132.   
  133.         /**  
  134.          * 响应消息  
  135.          */  
  136.         @Override  
  137.         public void handleMessage(Message msg) {   
  138.             SnakeView.this.update();   
  139.             SnakeView.this.invalidate();   
  140.         }   
  141.         /**  
  142.          * 向外提供人工的调用消息的接口  
  143.          * @param delayMillis  
  144.          */  
  145.         public void sleep(long delayMillis) {   
  146.             //注销消息   
  147.             this.removeMessages(0);   
  148.             //添加消息   
  149.             sendMessageDelayed(obtainMessage(0), delayMillis);   
  150.         }   
  151.     };   
  152.   
  153.   
  154.     /**  
  155.      * Constructs a SnakeView based on inflation from XML  
  156.      *   
  157.      * @param context  
  158.      * @param attrs  
  159.      */  
  160.     public SnakeView(Context context, AttributeSet attrs) {   
  161.         super(context, attrs);   
  162.         initSnakeView();   
  163.    }   
  164.   
  165.     public SnakeView(Context context, AttributeSet attrs, int defStyle) {   
  166.         super(context, attrs, defStyle);   
  167.         initSnakeView();   
  168.     }   
  169.     /**  
  170.      * 初始化界面的  
  171.      */  
  172.     private void initSnakeView() {   
  173.         setFocusable(true);   
  174.   
  175.         Resources r = this.getContext().getResources();   
  176.            
  177.         resetTiles(4);   
  178.         loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));   
  179.         loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));   
  180.         loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));   
  181.            
  182.     }   
  183.        
  184.     /**  
  185.      * 初始化新的游戏  
  186.      */  
  187.     private void initNewGame() {   
  188.         mSnakeTrail.clear();   
  189.         mAppleList.clear();   
  190.   
  191.         // For now we're just going to load up a short default eastbound snake   
  192.         // that's just turned north   
  193.         //设置初始化蛇的位置    
  194.            
  195.         mSnakeTrail.add(new Coordinate(77));   
  196.         mSnakeTrail.add(new Coordinate(67));   
  197.         mSnakeTrail.add(new Coordinate(57));   
  198.         mSnakeTrail.add(new Coordinate(47));   
  199.         mSnakeTrail.add(new Coordinate(37));   
  200.         mSnakeTrail.add(new Coordinate(27));   
  201.         mNextDirection = NORTH;   
  202.   
  203.         // Two apples to start with   
  204.         //设置苹果的位置   
  205.         addRandomApple();   
  206.         addRandomApple();   
  207.         //   
  208.         mMoveDelay = 600;   
  209.         //设置积分的   
  210.         mScore = 0;   
  211.     }   
  212.   
  213.   
  214.     /**  
  215.      * Given a ArrayList of coordinates, we need to flatten them into an array of  
  216.      * ints before we can stuff them into a map for flattening and storage.  
  217.      *   
  218.      * @param cvec : a ArrayList of Coordinate objects  
  219.      * @return : a simple array containing the x/y values of the coordinates  
  220.      * as [x1,y1,x2,y2,x3,y3...]  
  221.      */  
  222.     private int[] coordArrayListToArray(ArrayList<Coordinate> cvec) {   
  223.         int count = cvec.size();   
  224.         int[] rawArray = new int[count * 2];   
  225.         for (int index = 0; index < count; index++) {   
  226.             Coordinate c = cvec.get(index);   
  227.             rawArray[2 * index] = c.x;   
  228.             rawArray[2 * index + 1] = c.y;   
  229.         }   
  230.         return rawArray;   
  231.     }   
  232.   
  233.     /**  
  234.      * Save game state so that the user does not lose anything  
  235.      * if the game process is killed while we are in the   
  236.      * background.  
  237.      *   
  238.      * @return a Bundle with this view's state  
  239.      */  
  240.     public Bundle saveState() {   
  241.         Bundle map = new Bundle();   
  242.   
  243.         map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));   
  244.         map.putInt("mDirection", Integer.valueOf(mDirection));   
  245.         map.putInt("mNextDirection", Integer.valueOf(mNextDirection));   
  246.         map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));   
  247.         map.putLong("mScore", Long.valueOf(mScore));   
  248.         map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));   
  249.   
  250.         return map;   
  251.     }   
  252.   
  253.     /**  
  254.      * Given a flattened array of ordinate pairs, we reconstitute them into a  
  255.      * ArrayList of Coordinate objects  
  256.      *   
  257.      * @param rawArray : [x1,y1,x2,y2,...]  
  258.      * @return a ArrayList of Coordinates  
  259.      */  
  260.     private ArrayList<Coordinate> coordArrayToArrayList(int[] rawArray) {   
  261.         ArrayList<Coordinate> coordArrayList = new ArrayList<Coordinate>();   
  262.   
  263.         int coordCount = rawArray.length;   
  264.         for (int index = 0; index < coordCount; index += 2) {   
  265.             Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]);   
  266.             coordArrayList.add(c);   
  267.         }   
  268.         return coordArrayList;   
  269.     }   
  270.   
  271.     /**  
  272.      * Restore game state if our process is being relaunched  
  273.      *   
  274.      * @param icicle a Bundle containing the game state  
  275.      */  
  276.     public void restoreState(Bundle icicle) {   
  277.         setMode(PAUSE);   
  278.         //从资源中获取ArrayList   
  279.         mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));   
  280.         mDirection = icicle.getInt("mDirection");   
  281.         mNextDirection = icicle.getInt("mNextDirection");   
  282.         mMoveDelay = icicle.getLong("mMoveDelay");   
  283.         mScore = icicle.getLong("mScore");   
  284.         mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));   
  285.     }   
  286.   
  287.     /**   
  288.      * 重点的控制代码   
  289.      *   
  290.      * 实现键盘事件: 键盘主要起操作作用, 在任何的手机游戏中键盘都是起重要的用,要本游戏中,  
  291.      *  他就是起控制蛇的行走方向: 现在我们分析他的代码:   
  292.      *   就是通过判断那个键按下, 然后再给要走的方向(mDirection)赋值。   
  293.      *     
  294.      * handles key events in the game. Update the direction our snake is traveling  
  295.      * based on the DPAD. Ignore events that would cause the snake to immediately  
  296.      * turn back on itself.  
  297.      *   
  298.      * (non-Javadoc)  
  299.      *   
  300.      * @see android.view.View#onKeyDown(int, android.os.KeyEvent)  
  301.      */  
  302.     @Override  
  303.     public boolean onKeyDown(int keyCode, KeyEvent msg) {   
  304.   
  305.         if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {   
  306.             if (mMode == READY | mMode == LOSE) {   
  307.                 /*  
  308.                  * At the beginning of the game, or the end of a previous one,  
  309.                  * we should start a new game.  
  310.                  */  
  311.                 initNewGame();   
  312.                 setMode(RUNNING);   
  313.                 update();   
  314.                 return (true);   
  315.             }   
  316.   
  317.             if (mMode == PAUSE) {   
  318.                 /*  
  319.                  * If the game is merely paused, we should just continue where  
  320.                  * we left off.  
  321.                  */  
  322.                 setMode(RUNNING);   
  323.                 update();   
  324.                 return (true);   
  325.             }   
  326.   
  327.             if (mDirection != SOUTH) {   
  328.                 mNextDirection = NORTH;   
  329.             }   
  330.             return (true);   
  331.         }   
  332.   
  333.         if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {   
  334.             if (mDirection != NORTH) {   
  335.                 mNextDirection = SOUTH;   
  336.             }   
  337.             return (true);   
  338.         }   
  339.   
  340.         if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {   
  341.             if (mDirection != EAST) {   
  342.                 mNextDirection = WEST;   
  343.             }   
  344.             return (true);   
  345.         }   
  346.   
  347.         if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {   
  348.             if (mDirection != WEST) {   
  349.                 mNextDirection = EAST;   
  350.             }   
  351.             return (true);   
  352.         }   
  353.   
  354.         return super.onKeyDown(keyCode, msg);   
  355.     }   
  356.   
  357.     /**  
  358.      * Sets the TextView that will be used to give information (such as "Game  
  359.      * Over" to the user.  
  360.      *   
  361.      * @param newView  
  362.      */  
  363.     public void setTextView(TextView newView) {   
  364.         mStatusText = newView;   
  365.     }   
  366.   
  367.     /**  
  368.      * Updates the current mode of the application (RUNNING or PAUSED or the like)  
  369.      * as well as sets the visibility of textview for notification  
  370.      *   
  371.      * @param newMode  
  372.      */  
  373.     public void setMode(int newMode) {   
  374.         int oldMode = mMode;   
  375.         mMode = newMode;   
  376.   
  377.         if (newMode == RUNNING & oldMode != RUNNING) {   
  378.             mStatusText.setVisibility(View.INVISIBLE);   
  379.             update();   
  380.             return;   
  381.         }   
  382.   
  383.         Resources res = getContext().getResources();   
  384.         CharSequence str = "";   
  385.         if (newMode == PAUSE) {   
  386.             str = res.getText(R.string.mode_pause);   
  387.         }   
  388.         if (newMode == READY) {   
  389.             str = res.getText(R.string.mode_ready);   
  390.         }   
  391.         if (newMode == LOSE) {   
  392.             str = res.getString(R.string.mode_lose_prefix) + mScore   
  393.                   + res.getString(R.string.mode_lose_suffix);   
  394.         }   
  395.   
  396.         mStatusText.setText(str);   
  397.         mStatusText.setVisibility(View.VISIBLE);   
  398.     }   
  399.   
  400.     /**  
  401.      *   
  402.      * 生成苹果位置的代码:  
  403.      * 苹果的位置就是更简单了,他是随机生成的, 而且必须在现在蛇的位置相对远距离。  
  404.      *   
  405.      * Selects a random location within the garden that is not currently covered  
  406.      * by the snake. Currently _could_ go into an infinite loop if the snake  
  407.      * currently fills the garden, but we'll leave discovery of this prize to a  
  408.      * truly excellent snake-player.  
  409.      *   
  410.      */  
  411.     private void addRandomApple() {   
  412.         Coordinate newCoord = null;   
  413.         boolean found = false;   
  414.         while (!found) {   
  415.             //随机生成新的X,Y位置   
  416.             // Choose a new location for our apple   
  417.             int newX = 1 + RNG.nextInt(mXTileCount - 2);   
  418.             int newY = 1 + RNG.nextInt(mYTileCount - 2);   
  419.             newCoord = new Coordinate(newX, newY);   
  420.   
  421.             // Make sure it's not already under the snake   
  422.             boolean collision = false;   
  423.             int snakelength = mSnakeTrail.size();   
  424.             for (int index = 0; index < snakelength; index++) {   
  425.                 //检查一下存放的位置是否合理   
  426.                 if (mSnakeTrail.get(index).equals(newCoord)) {   
  427.                     collision = true;   
  428.                 }   
  429.             }   
  430.             // if we're here and there's been no collision, then we have   
  431.             // a good location for an apple. Otherwise, we'll circle back   
  432.             // and try again   
  433.             found = !collision;   
  434.         }   
  435.         if (newCoord == null) {   
  436.             Log.e(TAG, "Somehow ended up with a null newCoord!");   
  437.         }   
  438.         //添加苹果的列表中的   
  439.         mAppleList.add(newCoord);   
  440.     }   
  441.   
  442.   
  443.     /**  
  444.      * Handles the basic update loop, checking to see if we are in the running  
  445.      * state, determining if a move should be made, updating the snake's location.  
  446.      */  
  447.     public void update() {   
  448.         if (mMode == RUNNING) {   
  449.             long now = System.currentTimeMillis();   
  450.   
  451.             if (now - mLastMove > mMoveDelay) {   
  452.                 clearTiles();   
  453.                 updateWalls();   
  454.                 updateSnake();   
  455.                 updateApples();   
  456.                 mLastMove = now;   
  457.             }   
  458.             mRedrawHandler.sleep(mMoveDelay);   
  459.         }   
  460.   
  461.     }   
  462.   
  463.     /**  
  464.      * 调用以上的方法以循环的方式位置数组赋值以及图片的索引。  
  465.      *   
  466.      * Draws some walls.  
  467.      *   
  468.      */  
  469.     private void updateWalls() {   
  470.         for (int x = 0; x < mXTileCount; x++) {   
  471.             setTile(GREEN_STAR, x, 0);  //设置顶部的界限的位置    
  472.             setTile(GREEN_STAR, x, mYTileCount - 1);   //设置底部界限的位置    
  473.         }   
  474.         for (int y = 1; y < mYTileCount - 1; y++) {   
  475.             setTile(GREEN_STAR, 0, y);          //设置顶部的界限的位置    
  476.             setTile(GREEN_STAR, mXTileCount - 1, y);   //设置底部界限的位置    
  477.         }   
  478.     }   
  479.   
  480.     /**  
  481.      * Draws some apples.  
  482.      *   
  483.      */  
  484.     private void updateApples() {   
  485.         for (Coordinate c : mAppleList) {   
  486.             setTile(YELLOW_STAR, c.x, c.y);   
  487.         }   
  488.     }   
  489.   
  490.     /**  
  491.      * 设置当前蛇的方向位置:  
  492.      * 从以上的键盘代码我们可以看得出,程序中是通过触发来改变坐标(+1,-1)的方式来改蛇头的方向,  
  493.      *  可见坐标在游戏编程中的作用, 这个也是根据手机的屏幕是点阵的方式来显示, 所以坐标就是一个  
  494.      *  定位器。 在这里大家可能还有一个疑问。 就是就这个蛇什么能够以“7”字形来移动行走, 其实我们  
  495.      *  稍微仔细观察一下就知道了,在这里面, 他们也是通过坐标的传递来实现的, 只要把头部的坐标点  
  496.      *  依次赋给下一个点, 后面的每一个点都走过了头部所走过的点,而蛇的头部就是负责去获取坐标,整  
  497.      *  个蛇的行走起来就很自然和连贯。  坐标的方向变换又是通过判断那个方向按键的按下来改变的, 这  
  498.      *  样一来, 键盘的作用就发挥出来了。蛇吃苹果又是怎样去实现?上面我所说到的坐标就起了作用。在蛇  
  499.      *  所经过的每一个坐标, 他们都要在苹果所在的(ArrayList<Coordinate> mAppleList = new  
  500.      *   ArrayList<Coordinate>())坐标集里面集依次判断,若是坐标相同,那个这个苹果就被蛇吃了 。   
  501.      *     
  502.      * Figure out which way the snake is going, see if he's run into anything (the  
  503.      * walls, himself, or an apple). If he's not going to die, we then add to the  
  504.      * front and subtract from the rear in order to simulate motion. If we want to  
  505.      * grow him, we don't subtract from the rear.  
  506.      *   
  507.      */  
  508.     private void updateSnake() {   
  509.         boolean growSnake = false;   
  510.   
  511.         // grab the snake by the head   
  512.         //获取蛇的头部   
  513.         Coordinate head = mSnakeTrail.get(0);   
  514.         //创建一个新的蛇的头部应该的位置    
  515.         Coordinate newHead = new Coordinate(11);   
  516.         //根据当前的为方向设置坐标的信息   
  517.         mDirection = mNextDirection;   
  518.   
  519.         switch (mDirection) {   
  520.         case EAST: {   
  521.             newHead = new Coordinate(head.x + 1, head.y);   
  522.             break;   
  523.         }   
  524.         case WEST: {   
  525.             newHead = new Coordinate(head.x - 1, head.y);   
  526.             break;   
  527.         }   
  528.         case NORTH: {   
  529.             newHead = new Coordinate(head.x, head.y - 1);   
  530.             break;   
  531.         }   
  532.         case SOUTH: {   
  533.             newHead = new Coordinate(head.x, head.y + 1);   
  534.             break;   
  535.         }   
  536.         }   
  537.   
  538.         // Collision detection   
  539.         // For now we have a 1-square wall around the entire arena   
  540.         if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2)   
  541.                 || (newHead.y > mYTileCount - 2)) {   
  542.             setMode(LOSE);   
  543.             return;   
  544.   
  545.         }   
  546.   
  547.         // Look for collisions with itself   
  548.         int snakelength = mSnakeTrail.size();   
  549.         for (int snakeindex = 0; snakeindex < snakelength; snakeindex++) {   
  550.             Coordinate c = mSnakeTrail.get(snakeindex);   
  551.             if (c.equals(newHead)) {   
  552.                 setMode(LOSE);   
  553.                 return;   
  554.             }   
  555.         }   
  556.   
  557.         // Look for apples   
  558.         //查找苹果设置苹果新的位置的信息   
  559.         int applecount = mAppleList.size();   
  560.         for (int appleindex = 0; appleindex < applecount; appleindex++) {   
  561.             Coordinate c = mAppleList.get(appleindex);   
  562.             if (c.equals(newHead)) {   
  563.                 mAppleList.remove(c);   
  564.                 addRandomApple();   
  565.                    
  566.                 mScore++;   
  567.                 //设置的移动的速度   
  568.                 mMoveDelay *= 0.9;   
  569.   
  570.                 growSnake = true;   
  571.             }   
  572.         }   
  573.         //将蛇头的位置信息放在第一个的对象中方取值   
  574.         // push a new head onto the ArrayList and pull off the tail   
  575.         mSnakeTrail.add(0, newHead);   
  576.         // except if we want the snake to grow   
  577.         if (!growSnake) {   
  578.             mSnakeTrail.remove(mSnakeTrail.size() - 1);   
  579.         }   
  580.   
  581.         int index = 0;   
  582.         for (Coordinate c : mSnakeTrail) {   
  583.             if (index == 0) {   
  584.                 setTile(YELLOW_STAR, c.x, c.y);   
  585.             } else {   
  586.                 setTile(RED_STAR, c.x, c.y);   
  587.             }   
  588.             index++;   
  589.         }   
  590.   
  591.     }   
  592.   
  593.     /**  
  594.      * 用于存储每一个位点的x,y坐标信息  
  595.      * Simple class containing two integer values and a comparison function.  
  596.      * There's probably something I should use instead, but this was quick and  
  597.      * easy to build.  
  598.      *   
  599.      */  
  600.     private class Coordinate {   
  601.         public int x;   
  602.         public int y;   
  603.   
  604.         public Coordinate(int newX, int newY) {   
  605.             x = newX;   
  606.             y = newY;   
  607.         }   
  608.   
  609.         public boolean equals(Coordinate other) {   
  610.             if (x == other.x && y == other.y) {   
  611.                 return true;   
  612.             }   
  613.             return false;   
  614.         }   
  615.   
  616.         @Override  
  617.         public String toString() {   
  618.             return "Coordinate: [" + x + "," + y + "]";   
  619.         }   
  620.     }   
  621.        
  622. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值