android 项目实训——(三)

 // 更新
237     public void update() {
238         // 如果是处于运行状态
239         if (mMode == RUNNING) {
240  
241             long now = System.currentTimeMillis();
242  
243             // 如果当前时间距离最后一次移动的时间超过了延迟时间
244             if (now - mLastMoveTime > mMoveDelay) {
245                 //
246                 clearTiles();
247                 updateWalls();
248                 updateSnake();
249                 updateApples();
250                 mLastMoveTime = now;
251             }
252             //会话进程睡一个延迟时间单位
253             mRedrawHandler.sleep(mMoveDelay);
254         }
255  
256     }
257  
258     // 更新墙
259     private void updateWalls() {
260         Log.i(tag, "updateWalls");
261         for (int x = 0; x < mXTileCount; x++) {
262             // 给上边线的每个贴片位置设置一个绿色索引标识
263             setTile(GREEN_STAR, x, 0);
264             // 给下边线的每个贴片位置设置一个绿色索引标识
265             setTile(GREEN_STAR, x, mYTileCount - 1);
266         }
267         for (int y = 1; y < mYTileCount - 1; y++) {
268             // 给左边线的每个贴片位置设置一个绿色索引标识
269             setTile(GREEN_STAR, 0, y);
270             // 给右边线的每个贴片位置设置一个绿色索引标识
271             setTile(GREEN_STAR, mXTileCount - 1, y);
272         }
273     }
274  
275     // 更新苹果
276     private void updateApples() {
277         Log.i(tag, "updateApples");
278  
279         for (Coordinate c : mAppleList) {
280             setTile(YELLOW_STAR, c.x, c.y);
281         }
282     }
283  
284     // 更新蛇
285     private void updateSnake() {
286         // 生长标志
287         boolean growSnake = false;
288  
289         // 得到蛇头坐标
290         Coordinate head = mSnakeTrail.get(0);
291         // 初始化一个新的蛇头坐标
292         Coordinate newHead = new Coordinate(11);
293  
294         // 当前方向改成新的方向
295         mDirection = mNextDirection;
296  
297         // 根据方向确定蛇头新坐标
298         switch (mDirection) {
299         // 如果方向向东(右),那么X加1
300         case EAST: {
301             newHead = new Coordinate(head.x + 1, head.y);
302             break;
303         }
304             // 如果方向向西(左),那么X减1
305         case WEST: {
306             newHead = new Coordinate(head.x - 1, head.y);
307             break;
308         }
309             // 如果方向向北(上),那么Y减1
310         case NORTH: {
311             newHead = new Coordinate(head.x, head.y - 1);
312             break;
313         }
314             // 如果方向向南(下),那么Y加1
315         case SOUTH: {
316             newHead = new Coordinate(head.x, head.y + 1);
317             break;
318         }
319         }
320  
321         // 冲突检测 新蛇头是否四面墙重叠,那么游戏结束
322         if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2)
323                 || (newHead.y > mYTileCount - 2)) {
324             // 设置游戏状态为Lose
325             setMode(LOSE);
326             // 返回
327             return;
328  
329         }
330  
331         // 冲突检测 新蛇头是否和自身坐标重叠,重叠的话游戏也结束
332         int snakelength = mSnakeTrail.size();
333  
334         for (int snakeindex = 0; snakeindex < snakelength; snakeindex++) {
335             Coordinate c = mSnakeTrail.get(snakeindex);
336             if (c.equals(newHead)) {
337                 // 设置游戏状态为Lose
338                 setMode(LOSE);
339                 // 返回
340                 return;
341             }
342         }
343  
344         // 看新蛇头和苹果们是否重叠
345         int applecount = mAppleList.size();
346         for (int appleindex = 0; appleindex < applecount; appleindex++) {
347             Coordinate c = mAppleList.get(appleindex);
348             if (c.equals(newHead)) {
349                 // 如果重叠,苹果坐标从苹果列表中移除
350                 mAppleList.remove(c);
351                 // 再立刻增加一个新苹果
352                 addRandomApple();
353                 // 得分加一
354                 mScore++;
355                 // 延迟是以前的90%
356                 mMoveDelay *= 0.9;
357                 // 蛇增长标志改为真
358                 growSnake = true;
359             }
360         }
361  
362         // 在蛇头的位置增加一个新坐标
363         mSnakeTrail.add(0, newHead);
364         // 如果没有增长
365         if (!growSnake) {
366             // 如果蛇头没增长则删去最后一个坐标,也就相当于蛇向前走了一步^_^
367             mSnakeTrail.remove(mSnakeTrail.size() - 1);
368         }
369  
370         int index = 0;
371         // 重新设置一下颜色,蛇头式黄色的,蛇身是红色的
372         for (Coordinate c : mSnakeTrail) {
373             if (index == 0) {
374                 setTile(YELLOW_STAR, c.x, c.y);
375             else {
376                 setTile(RED_STAR, c.x, c.y);
377             }
378             index++;
379         }
380  
381     }
382  
383     // 定义坐标内部类
384     private class Coordinate {
385  
386         public int x;
387         public int y;
388  
389         // 构造函数
390         public Coordinate(int newX, int newY) {
391             x = newX;
392             y = newY;
393         }
394  
395         // 重写equals
396         public boolean equals(Coordinate other) {
397             if (x == other.x && y == other.y) {
398                 return true;
399             }
400             return false;
401         }
402  
403         // 重写toString
404         @Override
405         public String toString() {
406             return "Coordinate: [" + x + "," + y + "]";
407         }
408     }
409  
410     // 添加苹果
411     private void addRandomApple() {
412         // 新的坐标
413         Coordinate newCoord = null;
414         //
415         boolean flag = true;
416         // 为真的话在循环体内一直循环
417         while (flag) {
418             // 为苹果再找一个坐标,先随机一个X值
419             int newX = 1 + RNG.nextInt(mXTileCount - 2);
420             // 再随机一个Y值
421             int newY = 1 + RNG.nextInt(mYTileCount - 2);
422             // 新坐标
423             newCoord = new Coordinate(newX, newY);
424  
425             // 下面确保新苹果不在蛇身下,先假设没发生冲突
426             boolean collision = false;
427  
428             int snakelength = mSnakeTrail.size();
429             // 和蛇占据的所有坐标比较
430             for (int index = 0; index < snakelength; index++) {
431                 // 只要和蛇占据的任何一个坐标相同,即认为发生冲突了
432                 if (mSnakeTrail.get(index).equals(newCoord)) {
433                     collision = true;
434                 }
435             }
436             // 如果有冲突就继续循环,如果没冲突flag的值就是false,那么自然会退出循环,新坐标也就诞生了
437             flag = collision;
438         }
439  
440         if (newCoord == null) {
441             Log.e(tag, "Somehow ended up with a null newCoord!");
442         }
443         // 生成一个新苹果放在苹果列表中(两个苹果可能会重合吧)
444         mAppleList.add(newCoord);
445     }
446  
447     // 初始化游戏
448     private void initNewGame() {
449  
450         Log.e(tag, "initNewGame!");
451  
452         // 清空ArrayList列表
453         mSnakeTrail.clear();
454         mAppleList.clear();
455  
456         // 创建蛇身
457         mSnakeTrail.add(new Coordinate(77));
458         mSnakeTrail.add(new Coordinate(67));
459         mSnakeTrail.add(new Coordinate(57));
460         mSnakeTrail.add(new Coordinate(47));
461         mSnakeTrail.add(new Coordinate(37));
462         mSnakeTrail.add(new Coordinate(27));
463  
464         // 新的方向 :北方
465         mNextDirection = NORTH;
466  
467         // 开始都时候有2个苹果
468         addRandomApple();
469         addRandomApple();
470  
471         // 设置移动延迟
472         mMoveDelay = 600;
473         // 得分0
474         mScore = 0;
475     }
476  
477     // 保存状态
478     public Bundle saveState() {
479  
480         Bundle bundle = new Bundle();
481  
482         bundle.putIntArray("mAppleList", coordArrayListToArray(mAppleList));
483         bundle.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));
484  
485         bundle.putInt("mDirection", Integer.valueOf(mDirection));
486         bundle.putInt("mNextDirection", Integer.valueOf(mNextDirection));
487  
488         bundle.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
489         bundle.putLong("mScore", Long.valueOf(mScore));
490  
491         return bundle;
492     }
493  
494     // 恢复状态
495     public void restoreState(Bundle icicle) {
496  
497         setMode(PAUSE);
498  
499         mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));
500         mDirection = icicle.getInt("mDirection");
501         mNextDirection = icicle.getInt("mNextDirection");
502         mMoveDelay = icicle.getLong("mMoveDelay");
503         mScore = icicle.getLong("mScore");
504         mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
505     }
506  
507     // 整数数组转坐标数组
508     private ArrayList coordArrayToArrayList(int[] rawArray) {
509         ArrayList coordArrayList = new ArrayList();
510  
511         int coordCount = rawArray.length;
512         for (int index = 0; index < coordCount; index += 2) {
513             Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]);
514             coordArrayList.add(c);
515         }
516         return coordArrayList;
517     }
518  
519     // 坐标数组转整数数组
520     private int[] coordArrayListToArray(ArrayList cvec) {
521         int count = cvec.size();
522         int[] rawArray = new int[count * 2];
523         for (int index = 0; index < count; index++) {
524             Coordinate c = cvec.get(index);
525             rawArray[2 * index] = c.x;
526             rawArray[2 * index + 1] = c.y;
527         }
528         return rawArray;
529     }
530  
531 }

6、MainActivity

01 package android.basic.lesson48;
02  
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.widget.TextView;
06  
07 public class MainActivity extends Activity {
08  
09     private SnakeView mSnakeView;
10  
11     private static String ICICLE_KEY = "snake-view";
12  
13     /** Called when the activity is first created. */
14     @Override
15     public void onCreate(Bundle savedInstanceState) {
16  
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.main);
19  
20         mSnakeView = (SnakeView) findViewById(R.id.snake);
21         TextView tv = (TextView) findViewById(R.id.text);
22  
23         mSnakeView.setStatusTextView(tv);
24  
25         //检查存贮状态以确定是重新开始还是恢复状态
26         if (savedInstanceState == null) {
27             //存储状态为空,说明刚启动可以切换到准备状态
28             mSnakeView.setMode(SnakeView.READY);
29         else {
30             //已经保存过,那么就去恢复原有状态
31             Bundle bundle = savedInstanceState.getBundle(ICICLE_KEY);
32             if (bundle != null) {
33                 //恢复状态
34                 mSnakeView.restoreState(bundle);
35             else {
36                 //设置状态为暂停
37                 mSnakeView.setMode(SnakeView.PAUSE);
38             }
39         }
40     }
41  
42     //暂停事件被触发时
43     @Override
44     protected void onPause() {
45         super.onPause();
46         // Pause the game along with the activity
47         mSnakeView.setMode(SnakeView.PAUSE);
48     }
49  
50     //状态保存
51     @Override
52     public void onSaveInstanceState(Bundle outState) {
53         //存储游戏状态到View里
54         outState.putBundle(ICICLE_KEY, mSnakeView.saveState());
55     }
56 }

你自己继续研究代码,本节课就到这里吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值