Coordinatec=mSnakeTrail.get(snakeindex);
if(c.equals(newHead)){
setMode(LOSE);
return;
}
}
3.碰到墙了
//Collisiondetection
//Fornowwehavea1-squarewallaroundtheentirearena
if((newHead.x<1)||(newHead.y<1)||(newHead.x>mXTileCount-2)
||(newHead.y>mYTileCount-2)){
setMode(LOSE);
return;
}
源代码分析
Snake状态分析:
在snakeView中定义了snake游戏的几种状态:
privateintmMode=READY;
publicstaticfinalintPAUSE=0;//暂定
publicstaticfinalintREADY=1;//准备好了
publicstaticfinalintRUNNING=2;//正在运行
publicstaticfinalintLOSE=3;//结束,输了游戏
各种游戏状态
rady
running
paused
lose
以上状态是通过:
voidsetMode(intnewMode)函数实现。
如何实现画出小方块:
参看:
publicclassDrawViewextendsView{
privatefinalintmTileSize=12;
privatefinalStringTAG="DEMO";
privatePaintpa=newPaint();
privateBitmapmTileArray;
voidloadImage(){
Resourcesr=this.getContext().getResources();
Drawabletile=r.getDrawable(R.drawable.redstar);
Bitmapbitmap=Bitmap.createBitmap(mTileSize,mTileSize,
Bitmap.Config.ARGB_8888);
Canvascanvas=newCanvas(bitmap);
tile.setBounds(0,0,mTileSize,mTileSize);
tile.draw(canvas);
mTileArray=bitmap;
}
publicDrawView(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
//TODOAuto-generatedconstructorstub
loadImage();
x=10;
y=10;
Log.i(TAG,"DrawView2");
}
//如果没有这段代码,大家可以试一下,改用上面的代码,程序能否通过。
publicDrawView(Contextcontext,AttributeSetattrs){
super(context,attrs);
//TODOAuto-generatedconstructorstub
loadImage();
Log.i(TAG,"DrawView3");
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
Log.i(TAG,"onDraw1");
canvas.drawBitmap(mTileArray,x,y,pa);
}
}
通过上面的文章可以画出小方块,但注意到SnakeView一共有两构造函数,那个函数才真正起作用呢?
●publicSnakeView(Contextcontext,AttributeSetattrs)
●publicSnakeView(Contextcontext,AttributeSetattrs,intdefStyle)
通过加log的方式,判断是第一个构造函数起作用。
在第一个构造函数上方有一段注释:
通过XML文件构造出SnakeView
*ConstructsaSnakeViewbasedoninflationfromXML
如果不使用这个构造函数,将会造成错误,可以试一下,看一下结果是怎样!
本人得到如下的错误提示:
05-2114:
13:
26.079:
ERROR/AndroidRuntime(711):
Causedby:
java.lang.NoSuchMethodException:
DrawView
按键处理:
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
//TODOAuto-generatedmethodstub
if(keyCode==KeyEvent.KEYCODE_DPAD_UP){
Log.i(TAG,"KEYCODE_DPAD_UP");
}
returnsuper.onKeyDown(keyCode,event);
}
如何让我们的小方块动起来?
实现小方块动起来的秘密在于view的publicvoidinvalidate()
大家可以参看SDK文档中关于View中Drawing中的一小段话
Toforceaviewtodraw,callinvalidate().//为了让view重画,可以调用invalidate函数
方法:
1.在DrawView类中添加两个成员:
privateintx,y;
同时实现get,set方法,
2.在构造函数中添加他们的初始值,
3.修改onDraw
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
Log.i(TAG,"onDraw1");
canvas.drawBitmap(mTileArray,x,y,pa);
}
4.修改onKeyDown函数
@Override
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
//TODOAuto-generatedmethodstub
if(keyCode==KeyEvent.KEYCODE_DPAD_UP){
Log.i(TAG,"KEYCODE_DPAD_UP");
dv.setX(dv.getX()+10);
dv.invalidate();
}
returnsuper.onKeyDown(keyCode,event);
}
最后运行结果如下图:
附:
网络上关于snake分析的三篇文章
上一次我们大概讲解了下AndroidSDK中的演示程序Snake游戏的主框架,今天我看来看下实现的基础类TileView,从名称上不难看出这是一个方砖类,就是生成一个方块。
TileView使用了Android平台的显示基类View,View类是直接从java.lang.Object派生出来的,是各种控件比如TextView、EditView的基类,当然包括我们的窗口Activity类,这些在SDK文档中都说的比较清楚。
这里定义了5个int型全局的变量,分别是方砖的数量mTileSize;方砖水平x防线的数量mXTileCount;以及竖直y方向上的方砖数量mYTileCount,下面是一个相对偏移位置mXOffset和mYOffset;这里android123主让要大家了解如何自定义View在Android开发中,在一个View类中主要是重写onSizeChanged方法来控制改变部分,以及onDraw实现画布的修改,实现的简写如下:
@Override
protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){}
@Override
publicvoidonDraw(Canvascanvas){super.onDraw(canvas);}
我们自定义的TileView类需要自己添加一个构造方法,根据需要,我们还重载了一种包含样式的方法,这里大家可以多看下Gallery控件的实现,就好理解了,下面是基本框架。
publicTileView(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);}
publicTileView(Contextcontext,AttributeSetattrs){super(context,attrs);}
在贪食蛇游戏中我们知道Snake是移动的,所以加入了一个清除显示的clearTiles方法,通过一个二维数组保存一个gird网格型的运动轨迹,下一次我们将会讲解android贪食蛇的游戏逻辑和完整的关联拼接实现。
今天我们分析下最复杂的SnakeView的设计,它是派生于TileView方砖类,TileView构建是基于Android直接的显示类View,如果不明白的可以查看Android示例程序Snake贪食蛇代码分析
(二)一文有关TileView类的实现, 首先我们看到整个游戏分READY、PAUSE 、RUNNING 、LOSE四种mMode状态模式,分别对应准备、暂停、运行中、结束(死亡),毕竟贪食蛇没有胜利这个结果。
整个Snake的运行分4个方向,NORTH、SOUTH 、EAST、WEST分别对应了北、南、东、西四个方向,其中变量mDirection对应当前的方向,而mNextDirection对应下个运行时的位置。
这里星星分3种,使用的是一个Drawable图片,分RED_STAR、YELLOW_STAR和GREEN_STAR三种颜色,游戏的星星出现位置由Random随机数生成器来决定,这里Random一般和Timer系统时钟来随机生成更真实一些,通过一个Handler对象来控制画面的更新,使用了this.update();和this.invalidate();这两个本地方法,Update和invaildate均为android.view.View类的本地方法。
这里资源的使用通过Resourcesr=this.getContext().getResources();获取了r对象的实例,通过r.getDrawable(R.drawable.redstar)获取资源名为redstar的资源,返回的是一个Drawable对象。
对于按键信息,直接重写View类的onKeyDown方法,这里KeyEvent传递的是按键的映射,比如KEYCODE_DPAD_UP向上,KeyEvent.KEYCODE_DPAD_DOWN向下等等,详细的查看SDK中的onKeyDown
@Override
publicbooleanonKeyDown(intkeyCode,KeyEventmsg){
if(keyCode==KeyEvent.KEYCODE_DPAD_UP){}
}
整个游戏的控制流程就是上面这些,对于游戏的逻辑而言比较简单,这个贪食蛇并没有包含3D设计和类似Nokia的能量走廊、6边形轨迹,有空了我们一起来完善一个3D的贪食蛇游戏