android如何编写一个贪食蛇游戏,贪食蛇游戏android详解
这句代码是获取res/value/attrs.xml下自定义的属性值,attrs.xml中如下定义:Java代码 mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);这句是获取layout文件定义的UI参数中tileSize的值,没有定义则返回缺省值12。mTileSize代表小方格的尺寸。接下来要把游戏的界面分成很多个小方格来绘画,首.
这句代码是获取res/value/attrs.xml下自定义的属性值,attrs.xml中如下定义:
Java代码
mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
这句是获取layout文件定义的UI参数中tileSize的值,没有定义则返回缺省值12。mTileSize代表小方格的尺寸。
接下来要把游戏的界面分成很多个小方格来绘画,首先我们要知道界面可以分成几个空格,可以在onSzieChanged中获取初始化数据,onSizeChanged在View第一次启动时加载
Java代码
protectedstaticintmXTileCount;
protectedstaticintmYTileCount;
privatestaticintmXOffset;
privatestaticintmYOffset;
privateint[][] mTileGrid;
@Override
protectedvoidonSizeChanged(intw ,inth,intoldw,intoldh){
mXTileCount = (int) Math.floor(w/mTileSize);
mYTileCount = (int) Math.floor(h/mTileSize);
//不能分成整数个,得出剩余x y 的尺寸
mXOffset = ((w-(mTileSize * mXTileCount))/2);
mYOffset = ((h-(mTileSize * mYTileCount))/2);
mTileGrid =newint[mXTileCount][mYTileCount];
clearTiles();
}
publicvoidclearTiles(){
for(intx =0; x
for(inty=0; y
setTile(0, x, y);
}
}
}
publicvoidsetTile(inttileindex,intx,inty){
mTileGrid[x][y]=tileindex;
}
protected static int mXTileCount;
protected static int mYTileCount;
private static int mXOffset;
private static int mYOffset;
private int[][] mTileGrid;
@Override
protected void onSizeChanged(int w ,int h, int oldw,int oldh){
mXTileCount = (int) Math.floor(w/mTileSize);
mYTileCount = (int) Math.floor(h/mTileSize);
//不能分成整数个,得出剩余x y 的尺寸
mXOffset = ((w-(mTileSize * mXTileCount))/2);
mYOffset = ((h-(mTileSize * mYTileCount))/2);
mTileGrid = new int[mXTileCount][mYTileCount];
clearTiles();
}
public void clearTiles(){
for(int x = 0; x
for(int y=0; y
setTile(0, x, y);
}
}
}
public void setTile(int tileindex, int x, int y){
mTileGrid[x][y]=tileindex;
}
clearTiles()函数初始化mTileGrid,把mTileGrid所有值设为0,mTileGrid代表界面的所有方格
Java代码
privateBitmap[] mTileArray;
publicvoidresetTiles(inttilecount) {
mTileArray =newBitmap[tilecount];
}
publicvoidloadTile(intkey, Drawable tile){
Bitmap bitmap =Bitmap.createBitmap(mTileSize,mTileSize,Bitmap.Config.ARGB_8888);//创建位图
Canvas canvas=newCanvas(bitmap);//获取位图的canvas
tile.setBounds(0,0, mTileSize ,mTileSize);
tile.draw(canvas);//把tile所表示的图片画到canvas中
mTileArray[key]=bitmap;
}
private Bitmap[] mTileArray;
public void resetTiles(int tilecount) {
mTileArray = new Bitmap[tilecount];
}
public void loadTile(int key, Drawable tile){
Bitmap bitmap =Bitmap.createBitmap(mTileSize,mTileSize,Bitmap.Config.ARGB_8888); //创建位图
Canvas canvas= new Canvas(bitmap);//获取位图的canvas
tile.setBounds(0, 0, mTileSize ,mTileSize);
tile.draw(canvas); //把tile所表示的图片画到canvas中
mTileArray[key]=bitmap;
}
mTileArray用来存方格所用到的图片resetTiles(int)函数初始化图片的数量,loadTile(int
key,Drawable)加载图片存进mTileArray[key]中
Java代码
//覆盖onDraw类,操作canvas实现绘图
Paint mPaint=newPaint();
@Override
publicvoidonDraw(Canvas canvas){
super.onDraw(canvas);
for(intx=0; x
for(inty=0; y
if(mTileGrid[x][y]>0){
canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
mXOffset+x * mTileSize,
mYOffset+y * mTileSize,
mPaint);
}
}
}
}
//覆盖onDraw类,操作canvas实现绘图
Paint mPaint=new Paint();
@Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
for(int x=0; x
for(int y=0; y
if(mTileGrid[x][y]>0){
canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
mXOffset+x * mTileSize,
mYOffset+y * mTileSize,
mPaint);
}
}
}
}
4.
接下来看看SnakeView类
Java代码
//创建SnakeView,SnakeView继承TileView,重写构造函数
publicSnakeViewExm(Context context , AttributeSet attrs){
super(context,attrs);
initSnakeView();
}
publicSnakeViewExm(Context context, AttributeSet attrs,intdefStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
initSnakeView();
}
privatevoidinitSnakeView(){
setFocusable(true);//获得焦点
Resources r=getContext().getResources();
resetTiles(4);
loadTile(RED_STAR,r.getDrawable(R.drawable.redstar));
loadTile(YELLOW_STAR,r.getDrawable(R.drawable.yellowstar));
loadTile(GREEN_STAR,r.getDrawable(R.drawable.greenstar));
}
privatestaticfinalintRED_STAR =1;
privatestaticfinalintYELLOW_STAR =2;
privatestaticfinalintGREEN_STAR =3;
//创建SnakeView,SnakeView继承TileView,重写构造函数
public SnakeViewExm(Context context , AttributeSet attrs){
super(context,attrs);
initSnakeView();
}
public SnakeViewExm(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
initSnakeView();
}
private void initSnakeView(){
setFocusable(true);//获得焦点
Resources r=getContext().getResources();
resetTiles(4);
loadTile(RED_STAR,r.getDrawable(R.drawable.redstar));
loadTile(YELLOW_STAR,r.getDrawable(R.drawable.yellowstar));
loadTile(GREEN_STAR,r.getDrawable(R.drawable.greenstar));
}
private static final int RED_STAR = 1;
private static final int YELLOW_STAR = 2;
private static final int GREEN_STAR = 3;
initSnakeView()函数中设置了mTileArray的长度,并加载了三张图片
Java代码
//贪吃蛇当前的方向mDirection,下一刻方向mNextDirection
privateintmDirection= NORTH;
privateintmNextDirection =NORTH;
privatestaticfinalintNORTH=1;
privatestaticfinalintSOUTH=2;
privatestaticfinalintEAST=3;
privatestaticfinalintWEST=4;
privatelongmScore =0;//得分
privatelongmMoveDelay =600;//600毫秒后,自动行走
//贪吃蛇由几个方格组成,Coordiante 是表示一个方格的坐标类
//mAppleList 苹果列表,也就是给贪吃蛇吃的那个东西,
privateArrayList mSnakeTrail =newArrayList();
privateArrayList mAppleList=newArrayList();
privatevoidinitNewGame(){
mSnakeTrail.clear();
mAppleList.clear();
//贪吃蛇的坐标
mSnakeTrail.add(newCoordinate(7,7));
mSnakeTrail.add(newCoordinate(6,7));
mSnakeTrail.add(newCoordinate(5,7));
mSnakeTrail.add(newCoordinate(4,7));
mSnakeTrail.add(newCoordinate(3,7));
mSnakeTrail.add(newCoordinate(2,7));
mNextDirection = NORTH;
addRandomApple();
addRandomApple();
mMoveDelay =600;
mScore =0;
}
privateclassCoordinate{
publicintx;
publicinty;
publicCoordinate(intnewX,intnewY){
x=newX;
y=newY;
}
publicbooleanequals(Coordinate other){
if(x==other.x && y==other.y){
returntrue;
}
returnfalse;
}
@Override
publicString toString(){
return"Coordinate:["+ x +","+ y +"]";
}
}
//贪吃蛇当前的方向mDirection,下一刻方向mNextDirection
private int mDirection= NORTH;
private int mNextDirection =NORTH;
private static final int NORTH=1;
private static final int SOUTH=2;
private static final int EAST=3;
private static final int WEST=4;
private long mScore = 0; //得分
private long mMoveDelay = 600; //600毫秒后,自动行走
//贪吃蛇由几个方格组成,Coordiante 是表示一个方格的坐标类
//mAppleList 苹果列表,也就是给贪吃蛇吃的那个东西,
private ArrayList mSnakeTrail = new ArrayList();
private ArrayList mAppleList=new ArrayList();
private void initNewGame(){
mSnakeTrail.clear();
mAppleList.clear();
//贪吃蛇的坐标
mSnakeTrail.add(new Coordinate(7, 7));
mSnakeTrail.add(new Coordinate(6, 7));
mSnakeTrail.add(new Coordinate(5, 7));
mSnakeTrail.add(new Coordinate(4, 7));
mSnakeTrail.add(new Coordinate(3, 7));
mSnakeTrail.add(new Coordinate(2, 7));
mNextDirection = NORTH;
addRandomApple();
addRandomApple();
mMoveDelay = 600;
mScore = 0;
}
private class Coordinate{
public int x;
public int y;
public Coordinate(int newX, int newY){
x=newX;
y=newY;
}
public boolean equals(Coordinate other){
if(x==other.x && y==other.y){
return true;
}
return false;
}
@Override
public String toString(){
return "Coordinate:["+ x + "," + y + "]";
}
}
addRandomApplet()随进产生苹果的坐标位置,代码如下
Java代码
privatestaticfinalRandom RNG =newRandom();
privatevoidaddRandomApple(){
Coordinate newCoord =null;
booleanfound =false;
while(!found){
intnewX =1+ RNG.nextInt(mXTileCount-2);
intnewY =1+ RNG.nextInt(mYTileCount-2);
newCoord =newCoordinate(newX, newY);
booleancollision =false;
intsnakelength = mSnakeTrail.size();
//生成的位置不能和贪吃蛇的坐标一样
for(intindex =0; index
if(mSnakeTrail.get(index).equals(newCoord)){
collision=true;
}
}
found=!collision;
}
if(newCoord ==null){
Log.e(TAG,"Somehow ended up with a null newCoord");
}
mAppleList.add(newCoord);
}
private static final Random RNG =new Random();
private void addRandomApple(){
Coordinate newCoord = null;
boolean found = false;
while(!found){
int newX =1 + RNG.nextInt(mXTileCount-2);
int newY =1 + RNG.nextInt(mYTileCount-2);
newCoord = new Coordinate(newX, newY);
boolean collision = false;
int snakelength = mSnakeTrail.size();
//生成的位置不能和贪吃蛇的坐标一样
for(int index =0; index< snakelength;index++){
if(mSnakeTrail.get(index).equals(newCoord)){
collision=true;
}
}
found=!collision;
}
if(newCoord == null){
Log.e(TAG,"Somehow ended up with a null newCoord");
}
mAppleList.add(newCoord);
}
游戏初始化的参数在上面已经完成了,接下来是要给SnakeView添加事件响应
Java代码
//游戏状态的标识变量
privateintmMode = READY;
publicstaticfinalintPAUSE=0;
publicstaticfinalintREADY=1;
publicstaticfinalintRUNNING=2;
publicstaticfinalintLOSE=3;
@Override
publicbooleanonKeyDown(intkeyCode, KeyEvent msg){
//向上,如果是READY或LOST,则开始游戏
if(keyCode==KeyEvent.KEYCODE_DPAD_UP){
if(mMode ==READY | mMode ==LOSE){
initNewGame();//初始化
setMode(RUNNING);//设置状态
return(true);
}
if(mMode == PAUSE){
setMode(RUNNING);
update();
return(true);
}
//贪吃蛇不是向下走时,才可以向上
if(mDirection != SOUTH) {
mNextDirection = NORTH;
}
return(true);
}
if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
//贪吃蛇不是向上走时,才可以向下
if(mDirection!=NORTH){
mNextDirection=SOUTH;
}
return(true);
}
if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
//贪吃蛇不是向右走时,才可以向左
if(mDirection != EAST) {
mNextDirection = WEST;
}
return(true);
}
if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
if(mDirection != WEST) {
mNextDirection = EAST;
}
return(true);
}
returnsuper.onKeyDown(keyCode, msg);
}
//游戏状态的标识变量
private int mMode = READY;
public static final int PAUSE=0;
public static final int READY=1;
public static final int RUNNING=2;
public static final int LOSE=3;
@Override
public boolean onKeyDown(int keyCode, KeyEvent msg){
//向上,如果是READY或LOST,则开始游戏
if(keyCode==KeyEvent.KEYCODE_DPAD_UP){
if(mMode ==READY | mMode ==LOSE){
initNewGame(); //初始化
setMode(RUNNING);//设置状态
return(true);
}
if(mMode == PAUSE){
setMode(RUNNING);
update();
return (true);
}
//贪吃蛇不是向下走时,才可以向上
if (mDirection != SOUTH) {
mNextDirection = NORTH;
}
return (true);
}
if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
//贪吃蛇不是向上走时,才可以向下
if(mDirection!=NORTH){
mNextDirection=SOUTH;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
//贪吃蛇不是向右走时,才可以向左
if (mDirection != EAST) {
mNextDirection = WEST;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
if (mDirection != WEST) {
mNextDirection = EAST;
}
return (true);
}
return super.onKeyDown(keyCode, msg);
}
按下键盘键后,如果是刚开始游戏或者重新游戏时会调用update(),而其他状态则不会在这里调用更新,可以看出update()这个函数游戏中是一直在被调用的,下面我们看下代码这么实现update(),并且实现update()的循环调用
Java代码
privatelongmLastMove;
publicvoidupdate(){
//只有在运行中才会有数据更新
if(mMode==RUNNING){
longnow =System.currentTimeMillis();
//等待mMoveDelay时间,游戏自动更新
if(now - mLastMove >mMoveDelay){
clearTiles();
updateWalls();
updateSnake();
updateApples();
mLastMove=now;
}
mRedrawHandler.sleep(mMoveDelay);
}
}
privatevoidupdateWalls(){
//设置屏幕上下两边的方格图片
for(intx=0;x
setTile(GREEN_STAR, x,0);
setTile(GREEN_STAR, x,mYTileCount -1);
}
//设置屏幕左右两边的方格图片
for(inty=1;y
setTile(GREEN_STAR,0,y);
setTile(GREEN_STAR, mXTileCount -1,y);
}
}
privatevoidupdateSnake(){
booleangrowSnake =false;
Coordinate head =mSnakeTrail.get(0);
Coordinate newHead =newCoordinate(1,1);
mDirection =mNextDirection;
//获取下一步的坐标
switch(mDirection){
caseEAST:{
newHead =newCoordinate(head.x+1,head.y);
break;
}
caseWEST:{
newHead =newCoordinate(head.x-1,head.y);
break;
}
caseNORTH:{
newHead=newCoordinate(head.x,head.y-1);
break;
}
caseSOUTH:{
newHead=newCoordinate(head.x,head.y+1);
break;
}
}
//是否碰到“墙壁”
if((newHead.x<1)||(newHead.y<1)||(newHead.x>mXTileCount-2)
||(newHead.y>mYTileCount-2)){
setMode(LOSE);
return;
}
intsnakelength =mSnakeTrail.size();
//碰到自己
for(intsnakeindex=0;snakeindex
Coordinate c=mSnakeTrail.get(snakeindex);
if(c.equals(newHead)){
setMode(LOSE);
return;
}
}
intapplecount=mAppleList.size();
//吃到苹果
for(intappleindex =0;appleindex
Coordinate c=mAppleList.get(appleindex);
if(c.equals(newHead)){
mAppleList.remove(c);
addRandomApple();
mScore++;
mMoveDelay *=0.9;
growSnake =true;
}
}
mSnakeTrail.add(0,newHead);
if(!growSnake){
mSnakeTrail.remove(mSnakeTrail.size()-1);
}
//设置贪吃蛇的图片,第一个方格和其他方格不一样
intindex=0;
for(Coordinate c:mSnakeTrail){
if(index==0){
setTile(YELLOW_STAR, c.x,c.y);
}else{
setTile(RED_STAR,c.x,c.y);
}
index++;
}
}
//设置苹果的图片
privatevoidupdateApples(){
for(Coordinate c:mAppleList){
setTile(YELLOW_STAR,c.x,c.y);
}
}
private long mLastMove;
public void update(){
//只有在运行中才会有数据更新
if(mMode==RUNNING){
long now =System.currentTimeMillis();
//等待mMoveDelay时间,游戏自动更新
if(now - mLastMove >mMoveDelay){
clearTiles();
updateWalls();
updateSnake();
updateApples();
mLastMove=now;
}
mRedrawHandler.sleep(mMoveDelay);
}
}
private void updateWalls(){
//设置屏幕上下两边的方格图片
for(int x=0;x
setTile(GREEN_STAR, x,0);
setTile(GREEN_STAR, x,mYTileCount -1);
}
//设置屏幕左右两边的方格图片
for(int y=1;y
setTile(GREEN_STAR, 0,y);
setTile(GREEN_STAR, mXTileCount -1,y);
}
}
private void updateSnake(){
boolean growSnake =false;
Coordinate head =mSnakeTrail.get(0);
Coordinate newHead =new Coordinate(1,1);
mDirection =mNextDirection;
//获取下一步的坐标
switch(mDirection){
case EAST:{
newHead =new Coordinate(head.x+1,head.y);
break;
}
case WEST:{
newHead =new Coordinate(head.x-1,head.y);
break;
}
case NORTH:{
newHead=new Coordinate(head.x,head.y-1);
break;
}
case SOUTH:{
newHead=new Coordinate(head.x,head.y+1);
break;
}
}
//是否碰到“墙壁”
if((newHead.x<1)||(newHead.y<1)||(newHead.x>mXTileCount-2)
||(newHead.y>mYTileCount-2)){
setMode(LOSE);
return;
}
int snakelength =mSnakeTrail.size();
//碰到自己
for(int snakeindex=0;snakeindex
Coordinate c=mSnakeTrail.get(snakeindex);
if(c.equals(newHead)){
setMode(LOSE);
return;
}
}
int applecount=mAppleList.size();
//吃到苹果
for(int appleindex =0;appleindex
Coordinate c=mAppleList.get(appleindex);
if(c.equals(newHead)){
mAppleList.remove(c);
addRandomApple();
mScore++;
mMoveDelay *=0.9;
growSnake =true;
}
}
mSnakeTrail.add(0,newHead);
if(!growSnake){
mSnakeTrail.remove(mSnakeTrail.size()-1);
}
//设置贪吃蛇的图片,第一个方格和其他方格不一样
int index=0;
for(Coordinate c:mSnakeTrail){
if(index==0){
setTile(YELLOW_STAR, c.x,c.y);
}else{
setTile(RED_STAR,c.x,c.y);
}
index++;
}
}
//设置苹果的图片
private void updateApples(){
for(Coordinate c:mAppleList){
setTile(YELLOW_STAR,c.x,c.y);
}
}
上面update()函数中调用了mRedrawHandler.sleep(mMoveDelay);
mRedrawHandler对象是RedrawHandle的实例,mRedrawHandler继承Handler类
Java代码
privateRefreshHandler mRedrawHandler=newRefreshHandler();
classRefreshHandlerextendsHandler{
@Override
publicvoidhandleMessage(Message msg){
SnakeViewExm.this.update();
SnakeViewExm.this.invalidate();//重新调用onDraw()
}
publicvoidsleep(longdelayMillis){
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0),delayMillis);//调用sendMessageDelayed函数,线程等待delayMillis时间后发送信息,发送信息会调用handleMessage(msg)函数
}
}
private RefreshHandler mRedrawHandler=new RefreshHandler();
class RefreshHandler extends Handler{
@Override
public void handleMessage(Message msg){
SnakeViewExm.this.update();
SnakeViewExm.this.invalidate(); //重新调用onDraw()
}
public void sleep(long delayMillis){
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0),delayMillis);//调用sendMessageDelayed函数,线程等待delayMillis时间后发送信息,发送信息会调用handleMessage(msg)函数
}
}
到这里键盘事件响应就完成了,之前还有一个setMode(int)设置状态的函数没说,接下了就说它
Java代码
privateTextView mStatusText;//textView用来显示不同状态的信息
//可以通过Activity调用setTextView来实例化,这样就可以通过layout来配置textView的位置
publicvoidsetTextView(TextView newView){
mStatusText=newView;
}
publicvoidsetMode(intnewMode){
intoldMode = mMode;
mMode =newMode;
if(newMode==RUNNING & oldMode!=RUNNING){
mStatusText.setVisibility(View.INVISIBLE);//不显示TextView提示信息
update();
return;
}
Resources res=getContext().getResources();
CharSequence str="";
if(newMode ==PAUSE){
str=res.getText(R.string.mode_pause);//从资源文件string.xml中获取值
}
if(newMode==READY){
str=res.getText(R.string.mode_ready);
}
if(newMode==LOSE){
str=res.getString(R.string.mode_lose_prefix)+mScore
+res.getString(R.string.mode_lose_suffix);
}
mStatusText.setText(str);
mStatusText.setVisibility(View.VISIBLE);//显示TextView提示信息
}
private TextView mStatusText; //textView用来显示不同状态的信息
//可以通过Activity调用setTextView来实例化,这样就可以通过layout来配置textView的位置
public void setTextView(TextView newView){
mStatusText=newView;
}
public void setMode(int newMode){
int oldMode = mMode;
mMode =newMode;
if(newMode==RUNNING & oldMode!=RUNNING){
mStatusText.setVisibility(View.INVISIBLE);//不显示TextView提示信息
update();
return;
}
Resources res=getContext().getResources();
CharSequence str="";
if(newMode ==PAUSE){
str=res.getText(R.string.mode_pause);//从资源文件string.xml中获取值
}
if(newMode==READY){
str=res.getText(R.string.mode_ready);
}
if(newMode==LOSE){
str=res.getString(R.string.mode_lose_prefix)+mScore
+res.getString(R.string.mode_lose_suffix);
}
mStatusText.setText(str);
mStatusText.setVisibility(View.VISIBLE);//显示TextView提示信息
}
string.xml的配置可以在google sdk
自带的sample/snake里面找到,这里就不贴出来了;现在SnakeView功能基本齐全了,下面来看看Activity类
Java代码
publicclassSnakeextendsActivity {
privateSnakeView mSnakeView;
privatestaticString ICICLE_KEY ="snake-view";
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// No Title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.snake_layout);//layout文件自己在sdk sample/snake中找
mSnakeView = (SnakeView) findViewById(R.id.snake);
mSnakeView.setTextView((TextView) findViewById(R.id.text));
if(savedInstanceState ==null) {
// We were just launched -- set up a new game
mSnakeView.setMode(SnakeView.READY);
}else{
// We are being restored
Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
if(map !=null) {
mSnakeView.restoreState(map);
}else{
mSnakeView.setMode(SnakeView.PAUSE);
}
}
}
@Override
protectedvoidonPause() {
super.onPause();
// Pause the game along with the activity
mSnakeView.setMode(SnakeView.PAUSE);
}
@Override
publicvoidonSaveInstanceState(Bundle outState) {
//Store the game state
outState.putBundle(ICICLE_KEY, mSnakeView.saveState());
}
}
public class Snake extends Activity {
private SnakeView mSnakeView;
private static String ICICLE_KEY = "snake-view";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// No Title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.snake_layout);//layout文件自己在sdk sample/snake中找
mSnakeView = (SnakeView) findViewById(R.id.snake);
mSnakeView.setTextView((TextView) findViewById(R.id.text));
if (savedInstanceState == null) {
// We were just launched -- set up a new game
mSnakeView.setMode(SnakeView.READY);
} else {
// We are being restored
Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
if (map != null) {
mSnakeView.restoreState(map);
} else {
mSnakeView.setMode(SnakeView.PAUSE);
}
}
}
@Override
protected void onPause() {
super.onPause();
// Pause the game along with the activity
mSnakeView.setMode(SnakeView.PAUSE);
}
@Override
public void onSaveInstanceState(Bundle outState) {
//Store the game state
outState.putBundle(ICICLE_KEY, mSnakeView.saveState());
}
}
Snake类很简单,只是重写了onCreate、onPause和onSaveInstanceState函数,
其中onSaveInstanceState函数会在activity被杀掉之前被调用。上面调用了SnakeView中的saveState()函数返回游戏数据,和restoreState()函数还原保持的数据状态。
下面来看看SnakeView里面这两个函数的代码
Java代码
//保存数据
publicBundle saveState(){
Bundle map =newBundle();
map.putIntArray("mAppleList",coordArrayListToArray(mAppleList));//bundle只能存基本类型,所有要把ArrayList转换为int[],调用coordArrayListToArray进行转换
map.putInt("mDirection",Integer.valueOf(mDirection));
map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
map.putLong("mScore", Long.valueOf(mScore));
map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));
returnmap;
}
privateint[] coordArrayListToArray(ArrayList cvec){
intcount =cvec.size();
int[] array =newint[count*2];
for(intindex=0; index
Coordinate c=cvec.get(index);
array[2*index]=c.x;
array[2*index+1]=c.y;
}
returnarray;
}
//还原数据
publicvoidrestoreState(Bundle icicle){
setMode(PAUSE);
mAppleList =coordArrayToArrayList(icicle.getIntArray("mAppleList"));
mDirection=icicle.getInt("mDirection");
mNextDirection=icicle.getInt("mNextDirection");
mMoveDelay=icicle.getLong("mMoveDelay");
mScore=icicle.getLong("mScore");
mSnakeTrail=coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
}
privateArrayList coordArrayToArrayList(int[] rawArray){
ArrayList coordArrayList =newArrayList();
intcoordCount =rawArray.length;
for(intindex=0;index
Coordinate c=newCoordinate(rawArray[index],rawArray[index+1]);
coordArrayList.add(c);
}
returncoordArrayList;
}
//保存数据
public Bundle saveState(){
Bundle map =new Bundle();
map.putIntArray("mAppleList",coordArrayListToArray(mAppleList)); //bundle只能存基本类型,所有要把ArrayList转换为int[],调用coordArrayListToArray进行转换
map.putInt("mDirection",Integer.valueOf(mDirection));
map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
map.putLong("mScore", Long.valueOf(mScore));
map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));
return map;
}
private int[] coordArrayListToArray(ArrayList cvec){
int count =cvec.size();
int[] array =new int[count*2];
for(int index=0; index
Coordinate c=cvec.get(index);
array[2*index]=c.x;
array[2*index+1]=c.y;
}
return array;
}
//还原数据
public void restoreState(Bundle icicle){
setMode(PAUSE);
mAppleList =coordArrayToArrayList(icicle.getIntArray("mAppleList"));
mDirection=icicle.getInt("mDirection");
mNextDirection=icicle.getInt("mNextDirection");
mMoveDelay=icicle.getLong("mMoveDelay");
mScore=icicle.getLong("mScore");
mSnakeTrail=coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
}
private ArrayList coordArrayToArrayList(int[] rawArray){
ArrayList coordArrayList =new ArrayList();
int coordCount =rawArray.length;
for(int index=0;index
Coordinate c=new Coordinate(rawArray[index],rawArray[index+1]);
coordArrayList.add(c);
}
return coordArrayList;
}
到这里所有的类都讲解完,AndroidManifest.xml文件我这就不说了,请大家自己去看。这个游戏其实还有很多不完善的,比如说这个游戏并不支持暂停,只能玩到死,还有其他很多可以改善的地方,(我很懒的~~这里就不写了)大家如果有兴趣可以自己动手改下
更多推荐
所有评论(0)