这句代码是获取res/value/attrs.xml下自定义的属性值,attrs.xml中如下定义:

Java代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);

这句是获取layout文件定义的UI参数中tileSize的值,没有定义则返回缺省值12。mTileSize代表小方格的尺寸。

接下来要把游戏的界面分成很多个小方格来绘画,首先我们要知道界面可以分成几个空格,可以在onSzieChanged中获取初始化数据,onSizeChanged在View第一次启动时加载

Java代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

//覆盖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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

//创建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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

//贪吃蛇当前的方向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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

//游戏状态的标识变量

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

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代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

//保存数据

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文件我这就不说了,请大家自己去看。这个游戏其实还有很多不完善的,比如说这个游戏并不支持暂停,只能玩到死,还有其他很多可以改善的地方,(我很懒的~~这里就不写了)大家如果有兴趣可以自己动手改下

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐