今天带来一个贪吃蛇游戏,虽然我见过SDK例子里面有关于贪吃蛇的demo,但是那个过于繁琐,而且涉及太多不是贪吃蛇游戏算法的东西,不大适合初学者,
所以我编写了这个工程(其中算法可能和官方例子大相径庭),希望能帮到像我一样初学android,同时又对游戏编程感兴趣的你。
简单说明一下源码:
1,因为追求简洁,所以只有一个主要源文件——游戏的view类,此类中实现了最基本的贪吃蛇控制与显示模块(这些加起来不到区区两百行代码)
2,发现有的像我一样的初学者刚刚接触自定义view的知识,会不知道如何在view中实现button的功能,所以,代码中有一百多行左右来说明这个的用法(上下左右四个颜色不同的circle就是按键,按下还会产生动画效果)
再说明一点,这只是实现了最基本的贪吃蛇,并没有加入音效,管卡等处理,控制蛇运动速度的是Thread的延迟时间,加以更改便可以让蛇运动的更快,代码中重要地方有必要注释
还有就是在模拟器运行时会由于主机性能而照成蛇的运动会延迟一到两个节拍,而在真机测试时则不存在此问题。
下面加几个图片看看效果
部分代码:
GameViewSnake1类:
public GameViewSnake1(Context context) { super(context); flag=true; snake=new SNAKE[50]; food=new FOOD(); bitmapback=BitmapFactory.decodeResource(getResources(), R.drawable.snackwall); holder = this.getHolder(); holder.addCallback(this); setFocusable(true); setFocusableInTouchMode(true); paint=new Paint(); Snake_Init(); //new Thread(this).start(); // TODO Auto-generated constructor stub } public void Snake_Init() { Random r=new Random(); int m=r.nextInt(100); snake[0]=new SNAKE(x,y); switch(a%4) { case 0://右 snake[1]=new SNAKE(x-1,y); //snake[1].x=snake[0].x-1; //snake[1].y=snake[0].y; direct=RIGHT; break; case 1://左 snake[1]=new SNAKE(x+1,y); //snake[1].x=snake[0].x+1; //snake[1].y=snake[0].y; direct=LEFT; break; case 2://下 snake[1]=new SNAKE(x,y-1); //snake[1].x=snake[0].x; //snake[1].y=snake[0].y-1; direct=DOWN; break; case 3://上 snake[1]=new SNAKE(x,y+1); //snake[1].x=snake[0].x; //snake[1].y=snake[0].y+1; direct=UP; break; } Log.d("angang", "snake[0]"+snake[0].x+" "+snake[0].y+" "+"snake[1]"+snake[1].x+" "+snake[1].y+" direct="+direct); length=2; score=0; food.need=true; Snake_Food(); } public void Snake_Food() { int x0,y0,i; if(food.need) { while(food.need) { Random r=new Random(); int m=r.nextInt(100); int n=r.nextInt(100); food.x=x0; food.y=y0; for(i=0;i<length;i++) { if(snake[i].x==food.x && snake[i].y==food.y) break; } if(i==length)//没有随机到蛇身上,位置可以 break; }//while //food.need=false; } } public void DrawOneSnake(int x,int y,Canvas canvas) { paint.setColor(Color.GREEN); paint.setStyle(Paint.Style.FILL); canvas.drawRect(10+x*BLOCKSIZE, 10+y*BLOCKSIZE, 10+(x+1)*BLOCKSIZE, 10+(y+1)*BLOCKSIZE, paint); Log.d("angang", "draw snake("+x +y+")"); } public void DrawFood(int x,int y,Canvas canvas) { paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); canvas.drawRect(10+x*BLOCKSIZE, 10+y*BLOCKSIZE, 10+(x+1)*BLOCKSIZE, 10+(y+1)*BLOCKSIZE, paint); Log.d("angang", "DrawFood("+food.x +food.y+")"); } public void DrawWall(Canvas canvas) { canvas.drawBitmap(bitmapback, 0, 0, paint); paint.setColor(Color.DKGRAY); canvas.drawRect(8, 8, SCREENW-8, SCREENW-8, paint); } public void DrawButtuns(Canvas canvas) { paint.setStyle(Paint.Style.FILL); paint.setColor(Color.RED); if(up_down) {canvas.drawCircle(upx, upy, r2, paint);} else {canvas.drawCircle(upx, upy, r1, paint);} paint.setColor(Color.BLUE); //canvas.drawCircle(downx, downy, r1, paint); if(down_down) {canvas.drawCircle(downx, downy, r2, paint);} else {canvas.drawCircle(downx, downy, r1, paint);} paint.setColor(Color.CYAN); //canvas.drawRect(backx1, backy1, backx2, backy2, paint); if(esc_down) {canvas.drawRect(backx1+10, backy1+10, backx2-10, backy2-10, paint);} else {canvas.drawRect(backx1, backy1, backx2, backy2, paint);} } public void Draw() { Canvas canvas; canvas = holder.lockCanvas(); DrawWall(canvas); DrawFood(food.x,food.y,canvas); Log.d("angang", "draw food("+food.x +food.y+")"); DrawButtuns(canvas); for(int i=0;i<length;i++) { DrawOneSnake(snake[i].x,snake[i].y,canvas); Log.d("angang", "length="+length); } holder.unlockCanvasAndPost(canvas); } /* @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub Draw(canvas); super.onDraw(canvas); } */ @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub switch(event.getAction()) { case MotionEvent.ACTION_DOWN: /////////////////////////////////////////////////// if(event.getX()>=170 && event.getX()<(230)) //up { if(event.getY()>=520 && event.getY()<(580)) { up_down=true; Log.d("angang", "up 按下"); } } if(event.getX()>=170 && event.getX()<(230))//down { if(event.getY()>=620 && event.getY()<(680)) { down_down=true; } } if(event.getX()>=95 && event.getX()<(155)) //left { if(event.getY()>=570 && event.getY()<(630)) { left_down=true; } } if(event.getX()>=245 && event.getX()<(305)) //right { if(event.getY()>=570 && event.getY()<(630)) { right_down=true; } } if(event.getX()>=backx1 && event.getX()<(backx2)) //back { if(event.getY()>=backy1 && event.getY()<(backy2)) { esc_down=true; } } break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: ////////////////////////////////////////////////////// if(event.getX()>=170 && event.getX()<(230)) //up { if(event.getY()>=520 && event.getY()<(580)) { if(up_down) { up_down=false; direct=UP; Log.d("angang", "up 抬起"); } } } if(event.getX()>=170 && event.getX()<(230))//down { if(event.getY()>=620 && event.getY()<(680)) { if(down_down) { down_down=false; direct=DOWN; } } } if(event.getX()>=95 && event.getX()<(155)) //left { if(event.getY()>=570 && event.getY()<(630)) { if(left_down) { left_down=false; direct=LEFT; } } } if(event.getX()>=245 && event.getX()<(305)) //right { if(event.getY()>=570 && event.getY()<(630)) { if(right_down) { right_down=false; direct=RIGHT; } } } if(event.getX()>=backx1 && event.getX()<(backx2)) //back { if(event.getY()>=backy1 && event.getY()<(backy2)) { esc_down=false; flag=false; } } break; default: break; }//switch Draw(); //return super.onTouchEvent(event); return true; } public void run() { // TODO Auto-generated method stub int i; Log.d("angang", "draw food(**"+food.x +food.y+"**)"); SNAKE tempsnake=new SNAKE(0,0); while (flag) { //更新画面 Draw(); if(direct==ESC) { flag=false; //return; } //更新蛇的位置 tempsnake=snake[length-1]; for(i=length-1;i>0;i--) { //snake[i]=snake[i-1]; snake[i].x=snake[i-1].x; snake[i].y=snake[i-1].y; } //更新蛇头的位置,并判断是否出界 if(direct==LEFT) { snake[0].x--; if(snake[0].x<0) { flag=false; //return; } } if(direct==RIGHT) { snake[0].x++; if(snake[0].x>=GAME_WIDTH) { flag=false; //return; } } if(direct==UP) { snake[0].y--; if(snake[0].y<0) { flag=false; //return; } } if(direct==DOWN) { snake[0].y++; if(snake[0].y>=GAME_HEIGHT) { flag=false; //return; } } //判断蛇头是否撞到蛇身上 for(i=1;i<length;i++) { if(snake[0].x==snake[i].x && snake[0].y==snake[i].y) { flag=false; //return; } } //吃到东西,长长一段 if(snake[0].x==food.x && snake[0].y==food.y) { length++; //snake[length-1]=tempsnake; //snake[length-1].x=tempsnake.x; //snake[length-1].y=tempsnake.y; snake[length-1]=new SNAKE(tempsnake.x,tempsnake.y); food.need=true; Snake_Food(); } //若蛇长度达到最大 if(length>=SNAKE_LENGTH) { flag=false; //return; } Log.d("angang", "draw food(##"+food.x +food.y+"##)"+"flag="+flag); //postInvalidate(); try { Thread.sleep(500); } catch (Exception e) { } //synchronized (holder) { //Draw(); //} } }
原文:MySnake.zip