Snake游戏分析.docx
《Snake游戏分析.docx》由会员分享,可在线阅读,更多相关《Snake游戏分析.docx(77页珍藏版)》请在冰点文库上搜索。
Snake游戏分析
Snake游戏分析
Snake也是一个经典游戏了,Nokia蓝屏机的王牌游戏之一。
AndroidSDK1.5就有了它的身影。
我们这里就来详细解析一下AndroidSDKSample中的Snake工程。
本工程基于SDK2.3.3版本中的工程,路径为:
%Android_SDK_HOME%/samples/android-10/Snake
一、Eclipse工程
通过File-NewProject-Android-AndroidProject,选择“Createprojectfromexistingsample”创建自己的应用SnakeAndroid,如下图:
运行效果如下图:
二、工程结构和类图
其实Snake的工程蛮简单的,源文件就三个:
Snake.javaSnakeView.javaTileView.java。
Snake类是这个游戏的入口点,TitleView类进行游戏的绘画,SnakeView类则是对游戏控制操作的处理。
Coordinate,RefreshHandler是2个辅助类,也是SnakeView类中的内部类。
其中,Coordinate是一个点的坐标(x,y),RefreshHandler将RefreshHandler对象绑定某个线程并给它发送消息。
如下图:
任何游戏都需要有个引擎来推动游戏的运行,最简化的游戏引擎就是:
在一个线程中While循环,检测用户操作,对用户的操作作出反应,更新游戏的界面,直到用户退出游戏。
在Snake这个游戏中,辅助类RefreshHandler继承自Handler,用来把RefreshHandler与当前线程进行绑定,从而可以直接给线程发送消息并处理消息。
注意一点:
Handle对消息的处理都是异步。
RefreshHandler在Handler的基础上增加sleep()接口,用来每隔一个时间段后给当前线程发送一个消息。
handleMessage()方法在接受消息后,根据当前的游戏状态重绘界面,运行机制如下:
运行机制
这比较类似定时器的概念,在特定的时刻发送消息,根据消息处理相应的事件。
update()与sleep()间接的相互调用就构成了一个循环。
这里要注意:
mRedrawHandle绑定的是Avtivity所在的线程,也就是程序的主线程;另外由于sleep()是个异步函数,所以update()与sleep()之间的相互调用才没有构成死循环。
最后分析下游戏数据的保存机制,如下:
这里考虑了Activity的生命周期:
如果用户在游戏期间离开游戏界面,游戏暂停;或者由于内存比较紧张,Android关闭游戏释放内存,那么当用户返回游戏界面的时候恢复到上次离开时的界面。
三、源码解析
详细解析下源代码,由于代码量不大,以注释的方式列出如下:
1、Snake.java
Java代码
1./**
2. *
Title:
Snake
3. *
Copyright:
(C) 2007 The Android Open Source Project. Licensed under the Apache License, Version 2.0 (the "License")
4. * @author Gavin 标注
5. */
6.package com.deaboway.snake;
7.import android.app.Activity;
8.import android.os.Bundle;
9.import android.widget.TextView;
10./**
11. * Snake:
a simple game that everyone can enjoy.
12. *
13. * This is an implementation of the classic Game "Snake", in which you control a
14. * serpent roaming around the garden looking for apples. Be careful, though,
15. * because when you catch one, not only will you become longer, but you'll move
16. * faster. Running into yourself or the walls will end the game.
17. *
18. */
19.// 贪吃蛇:
经典游戏,在一个花园中找苹果吃,吃了苹果会变长,速度变快。
碰到自己和墙就挂掉。
20.public class Snake extends Activity {
21. private SnakeView mSnakeView;
22. private static String ICICLE_KEY = "snake-view";
23. /**
24. * Called when Activity is first created. Turns off the title bar, sets up
25. * the content views, and fires up the SnakeView.
26. *
27. */
28. // 在 activity 第一次创建时被调用
29. @Override
30. public void onCreate(Bundle savedInstanceState) {
31. super.onCreate(savedInstanceState);
32. setContentView(R.layout.snake_layout);
33. mSnakeView = (SnakeView) findViewById(R.id.snake);
34. mSnakeView.setTextView((TextView) findViewById(R.id.text));
35. // 检查存贮状态以确定是重新开始还是恢复状态
36. if (savedInstanceState == null) {
37. // 存储状态为空,说明刚启动可以切换到准备状态
38. mSnakeView.setMode(SnakeView.READY);
39. } else {
40. // 已经保存过,那么就去恢复原有状态
41. Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
42. if (map !
= null) {
43. // 恢复状态
44. mSnakeView.restoreState(map);
45. } else {
46. // 设置状态为暂停
47. mSnakeView.setMode(SnakeView.PAUSE);
48. }
49. }
50. }
51. // 暂停事件被触发时
52. @Override
53. protected void onPause() {
54. super.onPause();
55. // Pause the game along with the activity
56. mSnakeView.setMode(SnakeView.PAUSE);
57. }
58. // 状态保存
59. @Override
60. public void onSaveInstanceState(Bundle outState) {
61. // 存储游戏状态到View里
62. outState.putBundle(ICICLE_KEY, mSnakeView.saveState());
63. }
64.}
/**
*
Title:
Snake
*
Copyright:
(C)2007TheAndroidOpenSourceProject.LicensedundertheApacheLicense,Version2.0(the"License")
*@authorGavin标注
*/
packagecom.deaboway.snake;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.widget.TextView;
/**
*Snake:
asimplegamethateveryonecanenjoy.
*
*ThisisanimplementationoftheclassicGame"Snake",inwhichyoucontrola
*serpentroamingaroundthegardenlookingforapples.Becareful,though,
*becausewhenyoucatchone,notonlywillyoubecomelonger,butyou'llmove
*faster.Runningintoyourselforthewallswillendthegame.
*
*/
//贪吃蛇:
经典游戏,在一个花园中找苹果吃,吃了苹果会变长,速度变快。
碰到自己和墙就挂掉。
publicclassSnakeextendsActivity{
privateSnakeViewmSnakeView;
privatestaticStringICICLE_KEY="snake-view";
/**
*CalledwhenActivityisfirstcreated.Turnsoffthetitlebar,setsup
*thecontentviews,andfiresuptheSnakeView.
*
*/
//在activity第一次创建时被调用
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.snake_layout);
mSnakeView=(SnakeView)findViewById(R.id.snake);
mSnakeView.setTextView((TextView)findViewById(R.id.text));
//检查存贮状态以确定是重新开始还是恢复状态
if(savedInstanceState==null){
//存储状态为空,说明刚启动可以切换到准备状态
mSnakeView.setMode(SnakeView.READY);
}else{
//已经保存过,那么就去恢复原有状态
Bundlemap=savedInstanceState.getBundle(ICICLE_KEY);
if(map!
=null){
//恢复状态
mSnakeView.restoreState(map);
}else{
//设置状态为暂停
mSnakeView.setMode(SnakeView.PAUSE);
}
}
}
//暂停事件被触发时
@Override
protectedvoidonPause(){
super.onPause();
//Pausethegamealongwiththeactivity
mSnakeView.setMode(SnakeView.PAUSE);
}
//状态保存
@Override
publicvoidonSaveInstanceState(BundleoutState){
//存储游戏状态到View里
outState.putBundle(ICICLE_KEY,mSnakeView.saveState());
}
}
2、SnakeView.java
Java代码
1./**
2. *
Title:
Snake
3. *
Copyright:
(C) 2007 The Android Open Source Project. Licensed under the Apache License, Version 2.0 (the "License")
4. * @author Gavin 标注
5. */
6.
7.package com.deaboway.snake;
8.
9.import java.util.ArrayList;
10.import java.util.Random;
11.
12.import android.content.Context;
13.import android.content.res.Resources;
14.import android.os.Handler;
15.import android.os.Message;
16.import android.util.AttributeSet;
17.import android.os.Bundle;
18.import android.util.Log;
19.import android.view.KeyEvent;
20.import android.view.View;
21.import android.widget.TextView;
22.
23./**
24. * SnakeView:
implementation of a simple game of Snake
25. *
26. *
27. */
28.public class SnakeView extends TileView {
29.
30. private static final String TAG = "Deaboway";
31.
32. /**
33. * Current mode of application:
READY to run, RUNNING, or you have already
34. * lost. static final ints are used instead of an enum for performance
35. * reasons.
36. */
37. // 游戏状态,默认值是准备状态
38. private int mMode = READY;
39.
40. // 游戏的四个状态 暂停 准备 运行 和 失败
41. public static final int PAUSE = 0;
42. public static final int READY = 1;
43. public static final int RUNNING = 2;
44. public static final int LOSE = 3;
45.
46. // 游戏中蛇的前进方向,默认值北方
47. private int mDirection = NORTH;
48. // 下一步的移动方向,默认值北方
49. private int mNextDirection = NORTH;
50.
51. // 游戏方向设定 北 南 东 西
52. private static final int NORTH = 1;
53. private static final int SOUTH = 2;
54. private static final int EAST = 3;
55. private static final int WEST = 4;
56.
57. /**
58. * Labels for the drawables that will be loaded into the TileView class
59. */
60. // 三种游戏元
61. private static final int RED_STAR = 1;
62. private static final int YELLOW_STAR = 2;
63. private static final int GREEN_STAR = 3;
64.
65. /**
66. * mScore:
used to track the number of apples captured mMoveDelay:
number of
67. * milliseconds between snake movements. This will decrease as apples are
68. * captured.
69. */
70. // 游戏得分
71. private long mScore = 0;
72.
73. // 移动延迟
74. private long mMoveDelay = 600;
75.
76. /**
77. * mLastMove:
tracks the absolute time when the snake last moved, and is
78. * used to determine if a move should be made based on mMoveDelay.
79. */
80. // 最后一次移动时的毫秒时刻
81. private long mLastMove;
82.
83. /**
84. * mStatusText:
text shows to the user in some run states
85. */
86. // 显示游戏状态的文本组件
87. private TextView mStatusText;
88.
89. /**
90. * mSnakeTrail:
a list of Coordinates that make up the snake's body
91. * mAppleList:
the secret location of the juicy apples the snake craves.
92. */
93. // 蛇身数组(数组以坐标对象为元素)
94. private ArrayList mSnakeTrail = new ArrayList();
95.
96. // 苹果数组(数组以坐标对象为元素)
97. private ArrayList mAppleList = new ArrayList();
98.
99. /**
100. * Everyone needs a little randomness in their life
101. */
102. // 随机数
103. private static final Random RNG = new Random();
104.
105. /**
106. * Create a simple handler that we can use to cause animation to happen. We
107. * set ourselves as a target and we can use the sleep() function to cause an
108. * update/inv