5、SnakeView
001 | package android.basic.lesson48; |
002 |
003 | import java.util.ArrayList; |
004 | import java.util.Random; |
005 |
006 | import android.content.Context; |
007 | import android.content.res.Resources; |
008 | import android.os.Bundle; |
009 | import android.os.Handler; |
010 | import android.os.Message; |
011 | import android.util.AttributeSet; |
012 | import android.util.Log; |
013 | import android.view.KeyEvent; |
014 | import android.view.View; |
015 | import android.widget.TextView; |
016 |
017 | public 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 | } |