android 项目实训——(二)

来源:互联网 发布:jenkins 构建php 编辑:程序博客网 时间:2024/05/22 06:13

5、SnakeView

view source
print?
001package android.basic.lesson48;
002 
003import java.util.ArrayList;
004import java.util.Random;
005 
006import android.content.Context;
007import android.content.res.Resources;
008import android.os.Bundle;
009import android.os.Handler;
010import android.os.Message;
011import android.util.AttributeSet;
012import android.util.Log;
013import android.view.KeyEvent;
014import android.view.View;
015import android.widget.TextView;
016 
017public class SnakeView extends TileView {
018 
019    private static final String tag = "yao";
020 
021    // 游戏状态,默认值是准备状态
022    private int mMode = READY;
023 
024    // 游戏的四个状态 暂停 准备 运行 和 失败
025    public static final int PAUSE = 0;
026    public static final int READY = 1;
027    public static final int RUNNING = 2;
028    public static final int LOSE = 3;
029 
030    // 游戏中蛇的前进方向,默认值北方
031    private int mDirection = NORTH;
032    // 下一步的移动方向,默认值北方
033    private int mNextDirection = NORTH;
034 
035    // 游戏方向设定 北 南 东 西
036    private static final int NORTH = 1;
037    private static final int SOUTH = 2;
038    private static final int EAST = 3;
039    private static final int WEST = 4;
040 
041    // 三种游戏元�
042    private static final int RED_STAR = 1;
043    private static final int YELLOW_STAR = 2;
044    private static final int GREEN_STAR = 3;
045 
046    // 游戏得分
047    private long mScore = 0;
048 
049    // 移动延迟
050    private long mMoveDelay = 600;
051 
052    // 最后一次移动时的毫秒时刻
053    private long mLastMoveTime;
054 
055    // 显示游戏状态的文本组件
056    private TextView mStatusTextView;
057 
058    // 蛇身数组(数组以坐标对象为元素)
059    private ArrayList mSnakeTrail = new ArrayList();
060 
061    // 苹果数组(数组以坐标对象为元素)
062    private ArrayList mAppleList = new ArrayList();
063 
064    //随机数
065    private static final Random RNG = new Random();
066 
067    //
068    private RefreshHandler mRedrawHandler = new RefreshHandler();
069 
070    //一个Handler
071    class RefreshHandler extends Handler {
072 
073        //处理消息队列
074        @Override
075        public void handleMessage(Message msg) {
076            //更新View对象
077            SnakeView.this.update();
078            //强制重绘
079            SnakeView.this.invalidate();
080            //
081            Log.i(tag, "handleMessage|Thread Name="+Thread.currentThread().getName());
082        }
083 
084        //延迟发送消息
085        public void sleep(long delayMillis) {
086            this.removeMessages(0);
087            Log.i(tag, "sleep|Thread Name="+Thread.currentThread().getName());
088            sendMessageDelayed(obtainMessage(0), delayMillis);
089        }
090    };
091 
092    // 构造函数
093    public SnakeView(Context context, AttributeSet attrs) {
094        super(context, attrs);
095        Log.i(tag, "SnakeView Constructor");
096        // 构造时初始化
097        initSnakeView();
098 
099    }
100 
101    // 初始化
102    private void initSnakeView() {
103 
104        Log.e(tag, "initSnakeView");
105 
106        // 可选焦点
107        setFocusable(true);
108 
109        Resources r = this.getContext().getResources();
110 
111        // 设置贴片图片数组
112        resetTiles(4);
113 
114        // 把三种图片存到Bitmap对象数组
115        loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
116        loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
117        loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));
118 
119    }
120 
121    // 设置游戏状态
122    public void setMode(int newMode) {
123 
124        // 把当前游戏状态存入oldMode
125        int oldMode = mMode;
126        // 把游戏状态设置为新状态
127        mMode = newMode;
128 
129        Resources res = getContext().getResources();
130        CharSequence str = "";
131 
132        // 如果新状态是运行状态,且原有状态为不运行,那么就开始游戏
133        if (newMode == RUNNING & oldMode != RUNNING) {
134            // 设置mStatusTextView隐藏
135            mStatusTextView.setVisibility(View.INVISIBLE);
136            // 更新
137            update();
138            return;
139        }
140 
141        // 如果新状态是暂停状态,那么设置文本内容为暂停内容
142        if (newMode == PAUSE) {
143            str = res.getText(R.string.mode_pause);
144        }
145 
146        // 如果新状态是准备状态,那么设置文本内容为准备内容
147        if (newMode == READY) {
148            str = res.getText(R.string.mode_ready);
149        }
150 
151        // 如果新状态时失败状态,那么设置文本内容为失败内容
152        if (newMode == LOSE) {
153            // 把上轮的得分显示出来
154            str = res.getString(R.string.mode_lose_prefix) + mScore
155                    + res.getString(R.string.mode_lose_suffix);
156        }
157 
158        // 设置文本
159        mStatusTextView.setText(str);
160        // 显示该View
161        mStatusTextView.setVisibility(View.VISIBLE);
162    }
163 
164    // 设置状态显示View
165    public void setStatusTextView(TextView newView) {
166        mStatusTextView = newView;
167    }
168 
169    // 按键
170    public boolean onKeyDown(int keyCode, KeyEvent msg) {
171 
172        // 向上键
173        if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
174            // 准备状态或者失败状态时
175            if (mMode == READY | mMode == LOSE) {
176                // 初始化游戏
177                initNewGame();
178                // 设置游戏状态为运行
179                setMode(RUNNING);
180                // 更新
181                update();
182                // 消费掉
183                return (true);
184            }
185 
186            // 暂停状态时
187            if (mMode == PAUSE) {
188                // 设置成运行状态
189                setMode(RUNNING);
190                update();
191                // 消费掉
192                return (true);
193            }
194 
195            // 如果是运行状态时,如果方向原有方向不是向南,那么方向转右
196            if (mDirection != SOUTH) {
197                mNextDirection = NORTH;
198            }
199            return (true);
200        }
201 
202        // 向下键
203        if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
204            // 原方向不是向上时,方向转右
205            if (mDirection != NORTH) {
206                mNextDirection = SOUTH;
207            }
208            // 消费掉
209            return (true);
210        }
211 
212        // 向左键
213        if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
214            // 原方向不是向右时,方向转右
215            if (mDirection != EAST) {
216                mNextDirection = WEST;
217            }
218            // 消费掉
219            return (true);
220        }
221 
222        // 向右键
223        if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
224            // 原方向不是向左时,方向转右
225            if (mDirection != WEST) {
226                mNextDirection = EAST;
227            }
228            // 消费掉
229            return (true);
230        }
231 
232        // 按其他键时按原有功能返回
233        return super.onKeyDown(keyCode, msg);
234    }