背景
这学期的一门课要求分组完成一个课题,我们小组选题是基于安卓的贪吃蛇游戏,在网上确实源码满天飞,按照一贯的分工模式,可怜的我作为组长只有一个人支撑起整个开发过程。
简介
这个游戏现在功能已经基本实现,不过页面急待美化,代码更需优化。里面主要实现的功能是:不同速度下的游戏体验,两人联机效果的游戏体验,最高分的展示。
基本功能实现
基本原理是利用自定义view的onDraw()不断更新画布中的绘制对象来实现游戏画面,重写触摸事件来进行控制,根据坐标(point(x,y))进行一些判断。
实现过程
1.创建一个SnakeView继承View
public class SnakeView extends View {
public SnakeView(Context context, Handler handler) {
super(context);
mhandler=handler;
}
}
Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight=h;
mWidth=w;
}
2.初始画蛇体、食物、游戏背景
(1)创建蛇体
private int BOXWIDTH =0; //食物的边长,蛇体的宽度
private ArrayList<Point> mSnakeList; //蛇体可以看做是很多食物组成的
private Paint mSnakePaint; //用于画蛇的画笔
private int mSnakeDirection = 0; //蛇体运动的方向
private final int UP = 1,DOWN = 2,LEFT = 3,RIGHT =4;
private void initSnake(){
mSnakeList = new ArrayList<Point>();
mSnakePaint = new Paint();
mSnakePaint.setColor(Color.RED);
mSnakePaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置画蛇画笔的属性
mSnakeList.add(new Point(600,600));
mSnakeList.add(new Point(600,600+BOXWIDTH)); //初始化一条丑陋的蛇
mSnakeDirection = RIGHT;
}
(2)创建食物
private int BOXWIDTH =0; //食物的边长,蛇体的宽度
private Random mRandom; //用于产生随机数
private Point foodPosition; //食物的位置
private Paint mFoodPaint;//食物画笔
private boolean foodIsEaten; //食物是否已经被吃掉
private void initFood(){
// foodIsEaten=false;
foodPosition=new Point();
mFoodPaint=new Paint();
mFoodPaint.setColor(Color.CYAN);
mFoodPaint.setStyle(Paint.Style.FILL);
}
(3)初始化背景
private int mWidth; //view的宽
private int mHeight; //View的高
private static int sYOffset = 0,sXOffset = 0 ; // X坐标和Y坐标的偏移量,可以修改来缩小游戏范围
private Paint mBgPaint;//游戏背景画笔
private void initBg(){
mBgPaint = new Paint();
Paint paint = new Paint();
paint.setColor(Color.WHITE);
mWidth=getWidth();
mHeight=getHeight();
}
//画背景 这里通过sXOffset, sYOffset可以实现对蛇活动区域的限制
private void drawBg(Canvas canvas, Paint paint) {
canvas.drawColor(Color.WHITE);
Rect rect = new Rect(sXOffset, sYOffset, mWidth - sXOffset, mHeight - sYOffset);
canvas.drawRect(rect, paint);
}
3.绘制蛇(移动)、(next)食物的方法
(1)蛇的绘制
private void drawSnake(Canvas canvas, Paint paint) {
for(int i = 0 ; i < mSnakeList.size() ; i++ ) {
Point point = mSnakeList.get(i);
Rect rect = new Rect(point.x , point.y , point.x + BOXWIDTH , point.y + BOXWIDTH);
canvas.drawRect(rect, paint);
}
//蛇移动,更新list为下一次刷新做准备
snakeMove(mSnakeList, mSnakeDirection);
if(isFoodEaten()) { //如果吃了食物,长度加1
foodIsEaten = true;
} else { //如果没有吃食物,由于前进时加了一个 这里删除尾巴,出现移动的效果
mSnakeList.remove(mSnakeList.size() - 1);
}
}
public void snakeMove(ArrayList<Point> list , int direction) {
//Log.e(TAG," snakeMove ArrayList = " + list.toString());
Point orighead = list.get(0);
Point newhead = new Point();
//蛇前进,实现原理就是头加尾减,若吃到食物,头加尾不减
switch(direction) {
case UP:
newhead.x = orighead.x;
newhead.y = orighead.y - BOXWIDTH ;
break;
case DOWN:
newhead.x = orighead.x;
newhead.y = orighead.y + BOXWIDTH ;
break;
case LEFT:
newhead.x = orighead.x - BOXWIDTH;
newhead.y = orighead.y;
break;
case RIGHT:
newhead.x = orighead.x + BOXWIDTH ;
newhead.y = orighead.y;
break;
default:
break;
}
list.add(0, newhead);
overGame(newhead);//判断游戏是否结束
}
(2)食物的生成
private void drawFood(Canvas canvas, Paint paint) {
if(foodIsEaten) { //只在前一个食物被吃掉的情况下才产生食物
foodPosition.x = mRandom.nextInt(mWidth - 2*sXOffset - BOXWIDTH) + sXOffset ;
foodPosition.y = mRandom.nextInt(mWidth - 2*sYOffset - BOXWIDTH) + sYOffset ;
foodIsEaten = false;
}
Rect food = new Rect(foodPosition.x , foodPosition.y , foodPosition.x + BOXWIDTH , foodPosition.y + BOXWIDTH);
canvas.drawRect(food, paint);
}
4.游戏过程规则(吃食物,结束,得分)
//边界判断
priv