Android SDK 示例程序贪吃蛇详解
- 格式:doc
- 大小:207.00 KB
- 文档页数:14
附录1.SnakeView类package com.example.android_snake.view;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.Timer;import java.util.TimerTask;import com.example.android_snake.R;import com.example.android_snake.food.Food;import com.example.android_snake.snake.Body;import com.example.android_snake.snake.Head;import com.example.android_snake.snake.Snake;import com.example.android_snake.snake.SnakeDirection; import com.example.android_snake.stone.Stone;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.Style;import android.os.Handler;import android.util.DisplayMetrics;import android.view.Display;import android.view.MotionEvent;import android.view.View;import android.view.ViewManager;import android.view.WindowManager;import android.widget.Toast;public class SnakeView extends View {private Context context;private Bitmap headBitmap;private Bitmap bodyBitmap;private Bitmap foodBitmap;private Bitmap stoneBitmap;// 屏幕的高度和宽度private int screenHeight;private int screenWidth;// 每个小格子的高度和宽度private int eachHeight;private int eachWidth;private Snake snake;private Food food;private Stone stone;private int [] listx;private int [] listy;private Timer timer = new Timer();Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {moveSnake();invalidate();}};public SnakeView(Context context) {super(context);this.context = context;listx =new int[100];listy =new int[100];// 获得屏幕的高和宽DisplayMetrics metrics = new DisplayMetrics();WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);windowManager.getDefaultDisplay().getMetrics(metrics);screenHeight = metrics.heightPixels;screenWidth = metrics.widthPixels;eachHeight = screenHeight / 32;eachWidth = screenWidth / 20;// 初始化图片headBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.head);bodyBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.body);foodBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.food);stoneBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.stone);this.initSnake();this.initFood();this.initstone();gameRun();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint paint = new Paint();// 定义画笔paint.setColor(Color.GRAY);// 设置画笔颜色paint.setAntiAlias(true);// 去除锯齿paint.setStyle(Style.STROKE);// 设置空心实心paint.setTextSize(40);drawLines(canvas, paint);drawStone(canvas, paint);if(isCollide()){canvas.drawText("Game Over!", screenWidth/4, screenHeight/3, paint);canvas.drawText("得分", screenWidth/4, screenHeight/2, paint);timer.cancel();}else{this.drawSnake(canvas, paint);}boolean flag = IsRectCollision(snake.getHead().getPointX(), snake.getHead().getPointY(), eachWidth, eachHeight,food.getPointX(), food.getPointY(), eachWidth, eachHeight);if (flag) {food = null;snake.getBodyList().add(new Body());this.initFood();this.initstone();} else {this.drawFood(canvas, paint);this.drawStone(canvas, paint);}}//方向控制@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();SnakeDirection nowDir = snake.getSnakeDirection();int m = -screenHeight * x + screenHeight * screenWidth - screenWidth * y;int n = screenHeight * x - screenWidth * y;if ((m > 0 && n > 0) && (nowDir != SnakeDirection.DOWN)) {snake.setSnakeDirection(SnakeDirection.UP);} else if ((m > 0 && n < 0) && (nowDir != SnakeDirection.RIGHT)) { snake.setSnakeDirection(SnakeDirection.LEFT);} else if ((m < 0 && n > 0) && (nowDir != SnakeDirection.LEFT)) { snake.setSnakeDirection(SnakeDirection.RIGHT);} else if ((m < 0 && n < 0) && (nowDir != SnakeDirection.UP)) { snake.setSnakeDirection(SnakeDirection.DOWN);}return super.onTouchEvent(event);}public void gameRun() {timer.scheduleAtFixedRate(new TimerTask() {public void run() {handler.obtainMessage().sendToTarget();}}, 100, 400);}/** 画网格线*/public void drawLines(Canvas canvas, Paint paint) {int startX = 0, startY = 0;for (int i = 0; i < 100; i++) {canvas.drawLine(0, startY, screenWidth, startY, paint);startY = startY + eachHeight;}for (int i = 0; i < 100; i++) {canvas.drawLine(startX, 0, startX, screenHeight, paint);startX = startX + eachWidth;}canvas.drawLine(0, 0, screenWidth, screenHeight, paint);canvas.drawLine(0, screenHeight, screenWidth, 0, paint);}// 初始化蛇public void initSnake() {List<Body> bodies = new ArrayList<Body>();Head head = new Head(eachWidth * 4, eachHeight * 2, headBitmap);Body body1 = new Body(eachWidth * 3, eachHeight * 2, bodyBitmap);Body body2 = new Body(eachWidth * 2, eachHeight * 2, bodyBitmap);Body body3 = new Body(eachWidth * 1, eachHeight * 2, bodyBitmap);Body body4 = new Body(eachWidth * 0, eachHeight * 2, bodyBitmap);bodies.add(body1);bodies.add(body2);bodies.add(body3);bodies.add(body4);snake = new Snake(head, bodies, SnakeDirection.RIGHT);}// 画蛇public void drawSnake(Canvas canvas, Paint paint) {canvas.drawBitmap(headBitmap, snake.getHead().getPointX(), snake .getHead().getPointY(), paint);for (int i = 0; i < snake.getBodyList().size(); i++) {canvas.drawBitmap(bodyBitmap, snake.getBodyList().get(i).getPointX(), snake.getBodyList().get(i).getPointY(), paint);}}// 改变蛇身的位置public void changSnakePosition(int pointX, int pointY) {for (int i = snake.getBodyList().size() - 1; i > 0; i--) {snake.getBodyList().get(i).setPointX(snake.getBodyList().get(i - 1).getPointX());snake.getBodyList().get(i).setPointY(snake.getBodyList().get(i - 1).getPointY());}snake.getBodyList().get(0).setPointX(snake.getHead().getPointX());snake.getBodyList().get(0).setPointY(snake.getHead().getPointY());}// 移动蛇public void moveSnake() {int nowPointX = snake.getHead().getPointX();int nowPointY = snake.getHead().getPointY();if (snake.getSnakeDirection() == SnakeDirection.RIGHT) {changSnakePosition(nowPointX, nowPointY);if (nowPointX >= screenWidth - eachWidth) {snake.getHead().setPointX(0);} else {snake.getHead().setPointX(nowPointX + eachWidth);}} else if (snake.getSnakeDirection() == SnakeDirection.DOWN) { changSnakePosition(nowPointX, nowPointY);if (nowPointY >= screenHeight - eachHeight) {snake.getHead().setPointY(0);} else {snake.getHead().setPointY(nowPointY + eachHeight);}} else if (snake.getSnakeDirection() == SnakeDirection.LEFT) {changSnakePosition(nowPointX, nowPointY);if (nowPointX <= 0) {snake.getHead().setPointX(screenWidth - eachWidth);} else {snake.getHead().setPointX(nowPointX - eachWidth);}} else if (snake.getSnakeDirection() == SnakeDirection.UP) {changSnakePosition(nowPointX, nowPointY);if (nowPointY <= 0) {snake.getHead().setPointY(screenHeight - eachHeight);} else {snake.getHead().setPointY(nowPointY - eachHeight);}}}// 初始化foodpublic void initFood() {int x = new Random().nextInt(19);int y = new Random().nextInt(29);food = new Food(eachWidth * x, eachHeight * y, foodBitmap);}// 在界面上画出Foodpublic void drawFood(Canvas canvas, Paint paint) {if (food != null) {canvas.drawBitmap(foodBitmap, food.getPointX(), food.getPointY(),paint);}}// 初始化stonepublic void initstone() {int x = new Random().nextInt(17);int y = new Random().nextInt(23);stone = new Stone(eachWidth * x, eachHeight * y, stoneBitmap);int i=0,j=0;listx[i++]=x;listy[j++]=y;}// 在界面上画出Stonepublic void drawStone(Canvas canvas, Paint paint) {if (true) {canvas.drawBitmap(stoneBitmap, stone.getPointX(), stone.getPointY(),paint);for(int k=0;k<100;k++){//food = new Food(eachWidth * listx[k], eachHeight * listy[k], foodBitmap);//canvas.drawBitmap(stoneBitmap,listx[k], listy[k],paint);}}}/*** 矩形碰撞检测参数为x,y,width,height** @param x1* 第一个矩形的x* @param y1* 第一个矩形的y* @param w1* 第一个矩形的w* @param h1* 第一个矩形的h* @param x2* 第二个矩形的x* @param y2* 第二个矩形的y* @param w2* 第二个矩形的w* @param h2* 第二个矩形的h* @return是否碰撞*/public boolean IsRectCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {if (x2 > x1 && x2 >= x1 + w1) {return false;} else if (x2 < x1 && x2 <= x1 - w2) {return false;} else if (y2 > y1 && y2 >= y1 + h1) {return false;} else if (y2 < y1 && y2 <= y1 - h2) {return false;} else {return true;}}//检测蛇头是否与蛇身碰撞//检测蛇头与墙的碰撞//public boolean isCollide() {boolean flag = false;for (int i = 0; i < snake.getBodyList().size(); i++) {flag = IsRectCollision(snake.getHead().getPointX(),snake.getHead().getPointY(), eachWidth, eachHeight,snake.getBodyList().get(i).getPointX(),snake.getBodyList().get(i).getPointY(),eachWidth,eachHeight);for(int j=0;j<100;j++){flag = IsRectCollision(snake.getHead().getPointX(),snake.getHead().getPointY(), eachWidth, eachHeight,listx[j],listy[j], eachWidth,eachHeight);if(flag){break;}}if ((snake.getHead().getPointX() < 1) ||(snake.getHead().getPointY() < 1) ||(snake.getHead().getPointX() > screenWidth - 1)||(snake.getHead().getPointY() > screenHeight - 1)){flag = true;}if(flag){break;}}return flag;}}2.MainActivity类package com.example.android_snake;import com.example.android_snake.R;import com.example.android_snake.view.SnakeView;//Downloads By import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.MenuItem;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);//设置全屏getWindow().setFlags(youtParams.FLAG_FULLSCREEN, youtParams.FLAG_FULLSCREEN);SnakeView view = new SnakeView(this);setContentView(view);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu);return true;}}3.Food类package com.example.android_snake.food;import android.graphics.Bitmap;public class Food {private int pointX;private int pointY;private Bitmap foodBitmap;public Food() {super();}public Food(int pointX, int pointY, Bitmap foodBitmap) { super();this.pointX = pointX;this.pointY = pointY;this.foodBitmap = foodBitmap;}public int getPointX() {return pointX;}public void setPointX(int pointX) {this.pointX = pointX;}public int getPointY() {return pointY;}public void setPointY(int pointY) {this.pointY = pointY;}public Bitmap getFoodBitmap() {return foodBitmap;}public void setFoodBitmap(Bitmap foodBitmap) {this.foodBitmap = foodBitmap;}}4.Body类package com.example.android_snake.snake;import android.graphics.Bitmap;public class Body {private int pointX;private int pointY;private Bitmap bodyBitMap;public Body() {super();}public Body(int pointX, int pointY, Bitmap bodyBitMap) { super();this.pointX = pointX;this.pointY = pointY;this.bodyBitMap = bodyBitMap;}public int getPointX() {return pointX;}public void setPointX(int pointX) {this.pointX = pointX;}public int getPointY() {return pointY;}public void setPointY(int pointY) {this.pointY = pointY;}public Bitmap getBodyBitMap() {return bodyBitMap;}public void setBodyBitMap(Bitmap bodyBitMap) {this.bodyBitMap = bodyBitMap;}}5.Head类package com.example.android_snake.snake;import android.graphics.Bitmap;public class Head {private int pointX;private int pointY;private Bitmap headBitMap;public Head() {super();}public Head(int pointX, int pointY, Bitmap headBitMap) {super();this.pointX = pointX;this.pointY = pointY;this.headBitMap = headBitMap;}public int getPointX() {return pointX;}public void setPointX(int pointX) {this.pointX = pointX;}public int getPointY() {return pointY;}public void setPointY(int pointY) {this.pointY = pointY;}public Bitmap getHeadBitMap() {return headBitMap;}public void setHeadBitMap(Bitmap headBitMap) {this.headBitMap = headBitMap;}}6.Snake类package com.example.android_snake.snake;import java.util.ArrayList;import java.util.List;import android.graphics.Bitmap;public class Snake {private Head head;private Body body;private List<Body> bodyList;private SnakeDirection snakeDirection;public Snake(){}public Snake(Head head,List<Body> bodyList,SnakeDirection snakeDirection){ super();this.head = head;this.bodyList = bodyList;this.snakeDirection = snakeDirection;}public Head getHead() {return head;}public void setHead(Head head) {this.head = head;}public Body getBody() {return body;}public void setBody(Body body) {this.body = body;}public List<Body> getBodyList() {return bodyList;}public void setBodyList(List<Body> bodyList) {this.bodyList = bodyList;}public SnakeDirection getSnakeDirection() {return snakeDirection;}public void setSnakeDirection(SnakeDirection snakeDirection) { this.snakeDirection = snakeDirection;}}7.SnakeDirection类package com.example.android_snake.snake;public enum SnakeDirection {UP,DOWN,LEFT,RIGHT;}8.Stone类package com.example.android_snake.stone;import android.graphics.Bitmap;public class Stone {private int pointX;private int pointY;private Bitmap stoneBitmap;public Stone() {super();}public Stone(int pointX, int pointY, Bitmap foodBitmap) { super();this.pointX = pointX;this.pointY = pointY;this.stoneBitmap = stoneBitmap;}public int getPointX() {return pointX;}public void setPointX(int pointX) {this.pointX = pointX;}public int getPointY() {return pointY;}public void setPointY(int pointY) {this.pointY = pointY;}public Bitmap getStoneBitmap() {return stoneBitmap;}public void setFoodBitmap(Bitmap foodBitmap) { this.stoneBitmap = stoneBitmap;}}。
贪吃蛇系统功能需求分析
目录
1需求分析 (1)
2功能描述 (1)
3系统架构 (2)
4用例描述 (2)
4.1游戏开始或退出 (2)
4.2游戏难度选择 (2)
4.3游戏输赢判断 (3)
4.4得分查询 (3)
5用例图 (4)
6时序图 (5)
6.1开始与退出时序图 (5)
6.2游戏设置时序图 (5)
6.3玩游戏时序图 (6)
6.4游戏帮组时序图 (6)
7类图 (7)
8界面设计 (8)
1需求分析
此需求分析说明书对《贪吃蛇游戏》软件做了全面的用户需求分析,明确所要开发的游戏软件应具有的功能、性能与界面,使系统分析人员及软件开发人员能清楚地了解用户的需求,并在此基础上进一步提出概要设计说明书和完成后续设计与开发工作。
2功能描述
功能包括如下几点:
1)贪吃蛇的基本玩法:即可以用上、下、左、右键游戏区蛇的运动方向,使之向
着有食物的方向运动,并吞吃食物使身体增长,如果蛇在移动过程中,撞到墙
壁或身体交叉蛇头撞到自己的身体游戏结束。
2)调节蛇的运动速度:即用户可以调节蛇的速度来选择不同的难度。
3)选择关卡功能:即游戏分不同的难度级别,用户可以选择不同的难度级别进行
游戏。
4)游戏帮组:即用户可以查看游戏说明、查看英雄榜等。
3系统架构
4用例描述
4.1游戏开始或退出
4.2游戏难度选择
4.3游戏输赢判断
4.4得分查询
5用例图
6时序图
6.1开始与退出时序图
6.2游戏设置时序图
6.3玩游戏时序图
6.4游戏帮组时序图
7类图
8界面设计。
贪吃蛇设计说明书贪吃蛇设计说明书开发小组成员:目录1.需求陈述 (3)2.软件结构 (3)2.1用例图 (3)2.2类图 (4)2.3状态图---------------------------------------------------------------4 3.程序描述 (4)3.1功能 (5)3.2性能 (5)3.3输入项目 (5)3.4输出项目 (6)3.5算法 (6)3.6程序逻辑 (6)4.测试要点-----------------------------------------75.对象设计-------------------------------------------------------------------71.需求陈述1.用户需要开发一款命名为贪吃蛇的休闲小游戏2.开始游戏时,存在一条向右运动的小蛇和蛇需要吃掉的豆3.用户通过键盘的“上下左右”键控制小蛇分别向“上下左右”运动来吃掉豆,同时增加自身的长度4.小蛇吃掉游戏规定数量的豆后,游戏结束5.游戏分为初级、中级、高级6.小蛇不能碰到边界7.小蛇自身不能碰撞8.游戏可以暂停和重新开始9.游戏完成后计算所得分数10.游戏在任何时候都可以退出2.软件结构1.用例图2.类图3.状态图3.程序描述3.1功能小蛇可以通过方向键进行方向的变化。
屏幕上随机的出现豆,贪吃蛇在运动的过程中蛇头可以吃掉出现的的豆。
吃掉豆后,蛇的身体会增长一节。
当蛇的身体碰到四周的墙壁或者是自己的身体时,游戏会结束。
并且,在屏幕的上方有一个分数牌显示,游戏开始时分数为0,每当蛇吃掉一个豆,分数会增加10分。
而在游戏的过程中,玩家可以按菜单上的退出键或点击界面的关闭按钮退出游戏。
3.2性能本款游戏在界面设计上清晰明了、美观大方;在操作上简单、易懂。
有效率高,不易出错的优点。
本游戏着重于娱乐大众,并且有锻炼反应速度的特点。
3.3输入项目1)用户在界面菜单的操作有点击“开始”、“暂停”、“结束”、“重新开始”、“初级”、“中级”、“高级”。
贪吃蛇程序设计贪吃蛇是一款经典的电子游戏,其设计简单却极具挑战性,深受各个年龄段玩家的喜爱。
下面将详细介绍贪吃蛇程序的设计过程,包括基本规则、程序结构、实现方法以及可能的扩展功能。
基本规则贪吃蛇游戏的基本规则如下:1. 游戏界面是一个矩形网格,蛇在网格中移动。
2. 蛇由多个方块组成,初始时通常只有几个方块。
3. 玩家通过键盘控制蛇头的移动方向。
4. 蛇在吃到食物后,身体长度会增加一节。
5. 如果蛇头撞到自己的身体或屏幕边缘,游戏结束。
程序结构贪吃蛇程序主要包括以下几个部分:1. 游戏界面:显示蛇、食物和网格。
2. 蛇的移动逻辑:控制蛇的移动方向和速度。
3. 食物生成逻辑:随机在界面上生成食物。
4. 碰撞检测:检测蛇是否吃到食物或撞到自己及屏幕边缘。
5. 分数和生命值:记录玩家的得分和剩余生命。
实现方法1. 初始化- 设置游戏界面的大小。
- 初始化蛇的位置和长度。
- 随机生成食物的位置。
2. 游戏循环- 监听键盘输入,更新蛇头的移动方向。
- 根据移动方向更新蛇的位置。
- 检查蛇是否吃到食物,如果是,则增加蛇的长度和分数,并生成新的食物。
- 检查蛇是否撞到自己的身体或屏幕边缘,如果是,则结束游戏。
- 刷新游戏界面,显示当前的蛇、食物和分数。
3. 绘制界面- 使用图形库或API绘制网格、蛇和食物。
4. 处理用户输入- 监听键盘事件,根据用户的输入改变蛇的移动方向。
5. 碰撞检测- 检查蛇头是否与食物重叠,如果是,则触发吃食物的逻辑。
- 检查蛇头是否与蛇身其他部分重叠,如果是,则游戏结束。
- 检查蛇头是否到达屏幕边缘,如果是,则游戏结束。
可能的扩展功能1. 多种难度级别:根据游戏难度调整蛇的移动速度或食物的生成频率。
2. 特殊食物:例如,某些食物可以让蛇短暂加速或获得保护,避免碰撞。
3. 自定义皮肤:允许玩家选择或设计蛇和食物的外观。
4. 多人模式:支持多个玩家在同一设备或网络上进行游戏。
5. 成就系统:为玩家设置各种成就目标,增加游戏的可玩性。
微信⼩程序之贪吃蛇⼩游戏开发(完整代码)1:⾸先是index.wxml⽂件代码:<!--index.wxml--><canvas canvas-id='snakeCanvas' style='width:100%;height:100%;background-color:#ccc;'bindtouchstart='canvasStart' bindtouchmove='canvasMove' bindtouchend='canvasEnd'></canvas>2:然后是index.js⽂件代码//index.js//⼿指按下时的坐标var startX = 0;var startY = 0;//⼿指在canvas上移动的坐标var moveX = 0;var moveY = 0;//移动位置跟开始位置差值var X =0;var Y = 0;//⼿指⽅向var direction = null;//蛇移动⽅向var snakeDirection = "right";//⾝体对象(数组)var snakeBodys = [];//⾷物对象(数组)var foods = [];//窗⼝的宽⾼var windowWidth = 0;var windowHeight = 0;//⽤来获取屏幕⼤⼩wx.getSystemInfo({success: function (res) {windowWidth = res.windowWidth;windowHeight = res.windowHeight;}});//蛇头对象var snakeHead = {x: parseInt(Math.random() * (windowWidth-20)),y: parseInt(Math.random() * (windowHeight-20)),color: '#ff0000', //这⾥只能接受16进制没法写red这样w: 20,h: 20,reset:function(){this.x = parseInt(Math.random() * (windowWidth - 20));this.y = parseInt(Math.random() * (windowHeight - 20));}}//⽤于确定是否删除var collideBol = true;Page({canvasStart:function(e){startX = e.touches[0].x;startY = e.touches[0].y;},canvasMove:function(e){moveX = e.touches[0].x;moveY = e.touches[0].y;X = moveX - startX;Y = moveY - startY;if(Math.abs(X) > Math.abs(Y) && X > 0){direction = "right";}else if(Math.abs(X) > Math.abs(Y) && X < 0){direction = "left";}else if (Math.abs(Y) > Math.abs(X) && Y > 0) {direction = "down"; //这⾥很奇怪,是我数学坐标系没学好吗?明明Y轴正坐标是向上才对啊 }else if (Math.abs(Y) > Math.abs(X) && Y < 0) {direction = "top";}},canvasEnd:function(){snakeDirection = direction;},onReady:function(){var context = wx.createContext();//帧数var frameNum = 0;function draw(obj){context.setFillStyle(obj.color);context.beginPath();context.rect(obj.x, obj.y, obj.w, obj.h);context.closePath();context.fill();}//蛇头与⾷物碰撞函数function collide(obj1,obj2){var l1 = obj1.x;var r1 = obj1.w + l1;var t1 = obj1.y;var b1 = obj1.h+t1;var l2 = obj2.x;var r2 = obj2.w + l2;var t2 = obj2.y;var b2 = obj2.h + t2;//这⾥1是蛇头⽅块的上下左右边框 2是⾷物,同样是上下左右//(当蛇头⼜边框撞到⾷物左边框也就是⼤于左边框时就是碰撞了)if(r1>l2 && l1<r2 && b1 > t2 && t1< b2){return true;}else{return false;}}//蛇头与墙壁碰撞函数function collide2(obj1){var l1 = obj1.x;var r1 = obj1.w + l1;var t1 = obj1.y;var b1 = obj1.h + t1;if (l1 <=snakeHead.w || r1 >=windowWidth || t1 <=snakeHead.h || b1 >= windowHeight){ return true;}else{return false;}}function directionSet(){switch (snakeDirection) {case"left":snakeHead.x -= snakeHead.w;break;case"right":snakeHead.x += snakeHead.w;break;case"down":snakeHead.y += snakeHead.h;break;case"top":snakeHead.y -= snakeHead.h;break;}}function animate(){frameNum++;if (frameNum % 20 == 0){//蛇⾝体数组添加⼀个上⼀个的位置(⾝体对象)snakeBodys.push({x: snakeHead.x,y: snakeHead.y,w: 20,h: 20,color: "#00ff00"});if (snakeBodys.length > 4) {//移除不⽤的⾝体位置if (collideBol){snakeBodys.shift();}else{collideBol = true;}}directionSet();}//绘制蛇头draw(snakeHead);if (collide2(snakeHead)) {collideBol = false;snakeHead.reset();snakeBodys=[];draw(snakeHead);}//绘制蛇⾝for(var i=0;i<snakeBodys.length;i++){var snakeBody = snakeBodys[i];draw(snakeBody);}//绘制⾷物for(var i=0;i<foods.length;i++){var foodObj = foods[i];draw(foodObj);if (collide(snakeHead,foodObj)){//console.log("撞上了");collideBol = false;foodObj.reset();}}wx.drawCanvas({canvasId:"snakeCanvas",actions:context.getActions()});requestAnimationFrame(animate);}function rand(min,max){return parseInt(Math.random()*(max-min))+min;}//构造⾷物对象function Food() {var w = rand(10,20);this.w = w;this.h = w;this.x = rand(this.w, windowWidth - this.w);this.y = rand(this.h, windowHeight - this.h);this.color = "rgb("+rand(0,255)+","+rand(0,255)+","+rand(0,255)+")";//内部⽅法(重置⾷物位置颜⾊)this.reset = function (){this.x = rand(0,windowWidth);this.y = rand(0,windowHeight);this.color = "rgb(" + rand(0, 255) + "," + rand(0, 255) + "," + rand(0, 255) + ")"; }}for (var i = 0; i < 20; i++) {var foodObj = new Food();foods.push(foodObj);}animate();}})。
安卓贪吃蛇源代码#define M 200#include"graphics.h"#include<stdlib.h>#include<stdio.h>#include<string.h>#include<iostream.h>#include<dos.h>#include<conio.h>#include <windows.h>#define LEFT 97//A#define RIGHT 100//D#define DOWN 115//S#define UP 119//W#define Esc 0x011bint i,key;int score=0;int gamespeed=250;//游戏速度可根据实际情况自行调整struct Food{int x;//食物的横坐标int y;//食物的纵坐标int yes;//判断是否要出现食物的变量}food;//食物的结构体struct Snake{int x[M];int y[M];int node;//蛇的节数int direction;//蛇的移动方向int life;//蛇的生命,0表示活着,1表示死亡}snake;void Init();//图形驱动void Close();//图形结束void DrawK();//开始画面void GamePlay();//玩游戏的具体过程void GameOver();//游戏结束void PrScore();//输出成绩void main()//主函数{Init();//图形驱动DrawK();//开始画面GamePlay();//玩游戏的具体过程Close();//图形结束}void Init()//图形驱动{int gd=DETECT,gm;initgraph(&gd,&gm," ");/*此处为turboc的路径,读者可以根据自己的电脑而改*/cleardevice();}void DrawK()//开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙{setbkcolor(GREEN);setcolor(LIGHTRED);setlinestyle(0,0,5);//设置线型for(i=50;i<=600;i+=10)//画围墙{rectangle(i,40,i+10,49);//上边rectangle(i,451,i+10,460);//下边}for(i=40;i<=450;i+=10){rectangle(50,i,59,i+10);//左边rectangle(601,i,610,i+10);//右边}}void GamePlay()//玩游戏的具体过程{rand();//随机数发生器food.yes=1;//1表示需要出现新食物,0表示已经存在食物snake.life=0;//蛇活着snake.direction=1;//方向往右snake.x[0]=100;snake.y[0]=100;//舌头坐标snake.x[1]=110;snake.y[1]=100 ;snake.node=2;//蛇的节数PrScore();//输出分数while(1)//可重复玩游戏,按ESC键结束{while(!kbhit())//在没有按键的情况下,蛇自己移动身体{if(food.yes==1)//需要出现新食物{food.x=rand()%400+60;food.y=rand()%350+60;while(food.x%10!=0)//食物随即出现后必须让食物能够在整格内,这样才能让蛇迟到food.x++;while(food.y%10!=0)food.y++;food.yes=0;//画面上有食物了}if(food.yes==0)//画面上有食物就要显示{setcolor(GREEN);rectangle(food.x,food.y,food.x+10,food.y-10);}for(i=snake.node-1;i>0;i--)//蛇的每个环节往前移动,也就是贪吃蛇的关键算法{snake.x[i]=snake.x[i-1];snake.y[i]=snake.y[i-1];}switch(snake.direction)//1,2,3,4表示上下左右四个方向,通过这个判断来移动蛇头{case 1:snake.x[0]+=10;break;case 2:snake.x[0]-=10;break;case 3:snake.y[0]-=10;break;case 4:snake.y[0]+=10;break;}for(i=3;i<snake.node;i++)//从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来{if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0]){GameOver();//显示失败snake.life=1;break;}}if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||snake.y[0]>455)//蛇是否撞到墙壁{GameOver();//本次游戏结束snake.life=1;//蛇死}if(snake.life==1)//以上两种判断以后,如果蛇死就跳出内循环,重新开始break;if(snake.x[0]==food.x&&snake.y[0]==food.y)//吃到食物以后{setcolor(0);//把画面上的食物去掉rectangle(food.x,food.y,food.x+10,food.y-10);snake.x[snake.node]=-20;snake.y[snake.node]=-20;//新的一节先放在看不见得位置,下次循环就取前一节的位置snake.node++;//蛇的身体长一节food.yes=1;score+=10;PrScore();//输出新的得分}setcolor(WHITE);//画出蛇for(i=0;i<snake.node;i++)rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);Sleep(gamespeed);setcolor(0);//用黑色去除蛇的最后一节rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);}if(snake.life==1)//如果蛇死就跳出循环break;key=getchar();//接受案件if(key==Esc)//按ESC键退出break;else if(key==UP&&snake.direction!=4)snake.direction=3;else if(key==RIGHT&&snake.direction!=2)snake.direction=1;else if(key==LEFT&&snake.direction!=1)snake.direction=2;else if(key==DOWN&&snake.direction!=3)snake.direction=4;}//endwhile(1)}void GameOver()//游戏结束{cleardevice();PrScore();setcolor(RED);outtextxy(100,100,"我会回来的!!!!!");getch();}void PrScore()//输出成绩{char str[10];setfillstyle(SOLID_FILL,YELLOW);bar(50,15,220,35);setcolor(6);sprintf(str,"score:%d",score);outtextxy(55,20,str);}void Close()//图形结束{getch();closegraph();}。
基于安卓平台贪吃蛇游戏的设计一、选题依据1.设计(论文)题目:基于安卓平台贪吃蛇游戏的设计2.研究领域:通信运用3.设计(论文)工作的理论意义和应用价值目前随着移动设备越来越普及以及移动设备的硬件的提升,移动设备的功能越来越完善,android系统平台也日渐火热起来。
目前为止国内已经有很多Android系统的用户。
截止2013年Android系统的国内市场占有率已经过75%,在西欧以及北美智能手机市场占有率也在80%左右。
可见Android系统正处于发展的顶峰。
手机游戏作为Android系统平台的一个重要组成部分,正在被越来越多的人所重视。
全球在使用的移动电话已经超过59亿部,而且这个数字每天都在不断增加。
手机游戏潜在的市场比其他任何平台都要大。
二、设计研究的内容1.重点解决的问题(1)基于Android游戏动画的实现(2)游戏地图的数据结构的表示(3)游戏动画中的碰撞检测问题2.拟开展研究的几个主要方面:1理论上和实践上的意义关于Android游戏动画,基于安卓平台实现一个相对高效并且简单易用的游戏引擎,或者从其他手机平台移植相对较为成熟的游戏动画引擎。
解决此问题可以为贪吃蛇游戏以及其他类似的动画游戏提供流畅的动画效果,实现游戏引擎同时也可以提高游戏动画的代码复用率,提高游戏编程的效率。
深入理解Android系统的Dalvik虚拟机工作机制。
由于Android平台使用Java语言进行开发,谷歌的工程师改写了Java ME的虚拟机。
解决虚拟机垃圾回收时所造成的占用系统资源较大的问题,可以提高游戏的流畅性,提升用户的游戏体验。
解决游戏人工智能的解决方案,贪吃蛇游戏中,地图寻路问题并非如此简单,必须考虑多方面的因素。
触屏以及重力感应器等操控方式的处理问题。
在Android平台中相对传统的手机系统,Android系统提供多种传感器的调用接口。
探索使用手机导航球,重力感应,触屏操作等新型操控模式提高用户操作体验。
贪吃蛇游戏设计与分析贪吃蛇是一款非常经典的手机游戏,本文将使用MIDP实现这款著名的游戏。
基本概念介绍节:一条蛇可以看成有许多正方形的“小格子”拼凑成,我把它称作节。
节是蛇身上最小的单位。
段:当许多节连成一条直线,我称它为段。
上图的贪吃蛇只有一段,如果它拐弯就变成两段。
链表:用来保存每一段的状态,链表的元素单位是段。
且链表的最后一个元素表示蛇的头部段。
坐标系:MIDP中的坐标以左上角那点为(0,0),向右则x递增,向下则y 递增。
一条完整的贪吃蛇是由一段一段组成的。
链表中保存的第一个元素是蛇的尾巴段,最后一个元素是蛇的头部段。
当蛇运动的时候,它头部段增加一节而尾段减少一节。
如果它吃到了食物,尾部段就不减少一节。
也就是说,蛇是从头部段开始长的。
SnakeCanvas类中有以下代码:int[][] snake = new int[200][2];int snakeNum;int direction;private final int DIRECTION_UP = 0;private final int DIRECTION_DOWN = 1;private final int DIRECTION_LEFT = 2;private final int DIRECTION_RIGHT = 3;先存储贪吃蛇节点坐标,其中第二维下标为0的代表x坐标,第二维下标是1的代表y坐标; int snakeNum 表示已经使用的节点数量.int direction;private final int DIRECTION_UP = 0;private final int DIRECTION_DOWN = 1;private final int DIRECTION_LEFT = 2;private final int DIRECTION_RIGHT = 3;这段代码是设定贪吃蛇的运动方向,0代表向上,1代表向下,2代表向左,3代表向右。
任务4 贪吃蛇—蛇类(Snake)设计与实现【实验目标】1.熟悉GDI+绘图;2.会使用动态数组ArrayList;3.会使用Try和Catch捕获异常;4.会用IEnumerator接口;5.会编写蛇类的成员代码。
【实验内容】完成蛇类的创建,蛇类的成员主要包括构造函数、蛇序数属性、蛇位置属性、显示蛇和消除蛇的方法。
完成如下代码:重新开始游戏、只读蛇头位置属性、只读蛇是否碰到墙或碰到自身属性、蛇的运行方向属性、蛇的转向方法、蛇增长方法。
【蛇(Snake)类分析】(1)蛇由多个块组成,所以要包含一个整型数据,保存蛇头的编号即蛇的长度;(2)要有一个Point对象,保存蛇头的位置;(3)要有一个ArrayList对象,用于存放组成蛇的所有块;(4)蛇在场地运动,要用一个整型数据标识它的运动方向;(5)蛇要在场地中不断移动,如果蛇吃了豆,它自身要增长一块;(6)蛇的运行过程,就是蛇的不断显示过程;(7)在蛇消失时,要把块消除掉;(8)蛇运行过程中要不断地改变方向;(9)如果蛇头碰到了它自身,蛇就要死亡即程序结束。
【蛇(Snake)类代码编写】1.创建空白蛇类创建蛇的空白类,代码如下:using System;using System.Drawing;namespace贪吃蛇{///<summary>///Snake的摘要说明。
///</summary>public class Snake{}}2.蛇类主要成员—字段在蛇类中,有1个动态数组、3个字段,其中blockList、direction和headNumber 只在蛇类内部使用。
ArrayList blockList; //声明一个动态数组blockListprivate int headNumber; //蛇头序数或蛇长度private Point headPoint; //蛇头位置(左上角坐标)private int direction = 1; //0,1,2,3分别代表上、右、下、左3.蛇类主要成员—构造函数public Snake(Point vertex, int count)(1)功能根据游戏开始时蛇运动的默认方向和给定的参数,确定组成蛇的各块的位置,然后把各块添加到blockList中去;并初始化蛇的长度(蛇头的序数)字段headNumber 和蛇头位置字段headPoint。
贪吃蛇功能说明书(初稿)贪吃蛇(单词版)软件功能说明书1 开发背景“贪吃蛇”这个游戏对于80,90后的⼈来说是童年的记忆,可以将其说为是⼀个时代的经典,实现了传统贪吃蛇的游戏功能;现在⼈们对英语的重视程度越来越深,现在的⼩孩⼦在幼⼉园的时候就接受了简单的英语教学,熟记较多的英语单词对英语的学习起着巨⼤的积极作⽤,市⾯上的英语单词背记软件对于初⾼中学⽣来说易于接受,但是对于⼩学及以下的学⽣来说,这些软件的使⽤普遍率不⾼,年龄较⼩的孩⼦很难使⽤这些软件保持较长时间的集中⼒背单词。
基于这样的现实情况,【探路者团队】开发了贪吃蛇(单词版)的益智游戏软件。
该软件既可以实现贪吃蛇的游戏功能,⼜在原始功能的基础上增加单词拼写功能,使⽤户在娱乐的同时进⾏英语单词的学习。
2 开发⽬标开发本软件⼀⽅⾯是为了让80,90后⽤户重温童年的美好记忆,另⼀⽅⾯也是为了增加对英语学习兴趣较弱、意志⼒薄弱的中⼩学⽣学习英语的兴趣和动⼒,在游戏中记忆单词拼写。
本软件在使⽤过程中按照提供单词的顺序,“吃掉”软件当前提供的单词,并按照拼写顺序依次“吃”相应的字母才能完成此单词的任务,不提供⽤户跳过此单词进⾏下⼀单词的功能。
本软件只⽀持蛇头进⾏上下左右四个⽅位移动,暂不⽀持360°全⽅位移动蛇头。
3 软件⽤户本软件的应⽤⼈群主要是喜欢玩贪吃蛇,并且想通过游戏记单词的⼈群。
⽬前主要⽬标是学龄前⼉童,后期我们会对词库进⾏增加,以适合更多的⼈群。
4 软件功能描述4.1 贪吃蛇游戏基本功能4.1.1 运动功能⽤户可通过使⽤键盘上的上下左右⽅位键控制蛇的移动⽅向,蛇在控制的⽅向上进⾏直线前进。
4.1.2 吃⾷物功能当界⾯任意位置出现⾷物,⽤户使⽤⽅位键控制蛇移动到⾷物周围,当蛇头碰到⾷物时则表⽰贪吃蛇吃到此⾷物,界⾯上会在任意位置出现下⼀个⾷物,⽤户再次控制蛇去吃这⼀⾷物。
4.1.3 死亡判定功能当蛇头在前进⽅向上撞到墙壁或蛇头吃到蛇⾝时,给出死亡判定,并给出⽤户本次游戏得分,在下⼀次⽤户使⽤软件进⾏游戏时会将本次成绩加⼊到成绩排名列表中。
贪吃蛇程序设计说明书贪吃蛇游戏程序设计说明书题目:贪吃蛇游戏学校:系别:专业班级:姓名:学号:指导老师:日期:一、设计题目:贪吃蛇是一款经典的休闲游戏,一条蛇在密闭的围墙内,随机出现一个食物,通过控制方向键操作小蛇不停的朝着食物前进,直到吃掉食物。
每吃一个食物,小蛇都会长长一截,随之难度增大;当小蛇头撞到墙或自己时,小蛇死亡。
二、功能设计:本游戏要求实现以下几个功能:(1)用上、下、左、右键控制游戏区蛇的运动方向,使之吃食而使身体变长;(2)用户可以调节蛇的运行速度来选择不同的难度;(3)游戏分多个难度级别;(4)用户可自选颜色;(5)记录成绩前五名的游戏玩家;(6)增加背景音乐;(7)提高障碍物和游戏级别。
三、程序模块图:贪吃蛇游戏初始化图模块控制模块设置模块帮助模块墙体蛇身食物移动食物死亡变长绩等级音效四、算法流程图:是否否是否是开始初始化界面和蛇身放置食物获取按键开始运动碰到边界蛇吃到食蛇长大蛇死亡继续结束五、函数原型与功能1.主函数:void main()启动程序,触动其他函数。
2.初始化:void init ()设置背景框大小、蛇体初始值,随机产生食物。
3.随机产生食物:void setfoodcrd()设置食物生成坐标,0表示食物被吃。
4.画食物:void showfood()用矩形框来画食物5.画蛇:void showsnake()根据蛇的坐标和节数,循环用矩形框来画蛇。
6.蛇移动:void snakemove()根据按键,重设坐标7.改变蛇的方向:void changeskdir()响应用户的运动方向8.判断蛇是否死亡:void judgeslod判断蛇是否碰到自己或墙。
9.判断蛇是否吃到食物:void judgefood()判断是否吃到食物,吃食后变0,蛇增长一节。
10.结束游戏:void gameover()结束话语,并执行下一步。
六、基本代码#include#include#include#pragma comment(lib,"Winmm.lib")#include "MyTimer.h"#define SIZEMAX 100 /*蛇最大长度*/#define SPEED 100 /*初始速度*/#define len 20 /*蛇宽度*/#define lm 10 /*蛇每次移动距离*/#define initlen 600 /*初始化窗口正方形的长度*/ #define Min_snakelen 2 /*蛇的最小长度*/ typedef struct {int x,y;}DIR;int snakelen=Min_snakelen; /*蛇的长度*/int isfood=1; /*食物状态*/int isover=0; /*游戏状态*/int ispause=1; /*暂停状态*/int ismusic=1; /*音乐播放状态*/char dir; /*记录蛇运动的方向*/char c='d';DIR snake[500],food; /*定义蛇节点和食物的类型*/int speed=SPEED;void drawmap() /*画地图函数*/ {IMAGE img;char str[10];loadimage(&img,"贪吃蛇.jpg"); /*游戏界面*/ putimage(0,0,&img);loadimage(&img,"7.jpg"); /*侧栏提示*/putimage(600,0,&img);sprintf(str,"%d",snakelen);setfont(30,0,"宋体");setbkmode(TRANSPARENT);outtextxy(620,10,"操作说明:");setfont(20,0,"宋体");outtextxy(615,50,"awsd控制方向键");outtextxy(615,80,"p键暂停");outtextxy(615,110,"o键继续");outtextxy(615,200,"esc键退出");outtextxy(615,140,"l键暂停音乐");outtextxy(615,170,"k键继续播放");outtextxy(730,250,str);outtextxy(620,250,"蛇当前长度");}void init() /*初始化蛇函数*/ {int i;IMAGE img;snake[0].x=9*len+lm;snake[0].y=4*len+lm;loadimage(&img,"1.jpg");putimage(snake[0].x-lm,snake[0].y-lm,&img); for(i=1;i<snakelen;i++)< p="">{snake[i].x=len*(9-i)+lm;snake[i].y=len*4+lm;loadimage(&img, "2.jpg");putimage(snake[i].x-lm,snake[i].y-lm, &img); }}void showsnake() /*画蛇函数*/{int i;IMAGE img;loadimage(&img, "1.jpg");putimage(snake[0].x-lm,snake[0].y-lm , &img); loadimage(&img, "2.jpg");for(i=1;i<snakelen;i++)< p="">putimage(snake[i].x-lm,snake[i].y-lm, &img); }void snakemove() /*画动蛇函数*/{int i;int mx=snake[0].x;int my=snake[0].y;switch(dir){case 'a':mx-=len;break;case 'd':mx+=len;break;case 'w':my-=len;break;case 's':my+=len;break;default:break;}for(i=snakelen-1;i>=0;i--){snake[i+1].x=snake[i].x;snake[i+1].y=snake[i].y;}snake[0].x=mx;snake[0].y=my;showsnake();}int ceshiover() /*检测游戏结束函数*/{int i;if(snake[0].x<0||snake[0].x>30*len-lm||snake[0].y<0||snake[0].y>30*len-lm) return 1;for(i=1;i<snakelen;i++)< p="">{if(snake[0].x==snake[i].x&&snake[0].y==snake[i].y) return 1;}return 0;}int foodinsnake() /*检测食物是否在蛇上函数*/ {for(int i=0;i<snakelen;i++)< p="">if(food.x==snake[i].x&&food.y==snake[i].y)return 1;elsereturn 0;}void showfood() /*画食物函数*/{IMAGE img;do{food.x=(rand()%30)*len+lm;food.y=(rand()%30)*len+lm;}while(foodinsnake());loadimage(&img, "3.jpg");putimage(food.x-lm,food.y-lm , &img);isfood=0;}void kmusic(){if(ismusic==0)mciSendString("pause mymusic",NULL,0,NULL);if(ismusic==1)mciSendString("resume mymusic",NULL,0,NULL);}void playbkmusic() /*播放背景音乐函数*/{mciSendString("open 超级玛丽.mp3 alias mymusic", NULL, 0, NULL);mciSendString("play mymusic repeat", NULL, 0, NULL);}void playgame() /*玩游戏函数*/{c='d'; //蛇开始向右移动isover=0;snakelen=Min_snakelen;dir='d';IMAGE img;MyTimer t; //定义精确延时对象int T=200; // 延长时间drawmap(); //画游戏地图init(); //画小蛇初始位置while(!isover){if(ispause){snakemove();FlushBatchDraw(); //批量绘图EndBatchDraw(); //结束批量绘图if(snake[0].x==food.x&&snake[0].y==food.y){ snakelen++;isfood=1;}if(isfood)showfood();if(snakelen<35)T=200-3*snakelen;t.Sleep(T);BeginBatchDraw(); // 开始批量绘图模式,防止闪烁问题drawmap();loadimage(&img, "3.jpg"); // 加载食物图片putimage(food.x-lm,food.y-lm , &img);};//按键控制if(kbhit())c=getch();switch(c){case 'a':if(dir!='d'){dir=c;}break;case 'd':if(dir!='a'){dir=c;}break;case 'w':if(dir!='s'){dir=c;}break;case 's':if(dir!='w'){dir=c;}break;case 27: exit(0); break; //游戏退出case 'p': ispause=0;break; //p暂停case 'o': ispause=1;break; //o继续游戏case 'l': ismusic=0;break; //l暂停音乐case 'k': ismusic=1;break; //k继续播放default:break;}kmusic(); //音乐控制播放//判断游戏结束if(ceshiover())isover=1;//判断是否重新再来HWND wnd = GetHWnd(); //获取窗口句柄if(isover)if (MessageBox(wnd, "游戏结束。
北京领航致远科技有限公司 http://www.leadfar.org 作者:李腾飞 e-mail:tengfei.lee@qq.com QQ:1226369586 Blog:http://blog.csdn.net/li_tengfei 简介 小到一个游戏,大到复杂的企业级应用,都可以称之为一个项目,所有项目的开发,都可以遵循相同的基本开发过程:需求->分析->设计->实现
需求
请看演示 北京领航致远科技有限公司 http://www.leadfar.org
作者:李腾飞 e-mail:tengfei.lee@qq.com QQ:1226369586 Blog:http://blog.csdn.net/li_tengfei 北京领航致远科技有限公司 http://www.leadfar.org
作者:李腾飞 e-mail:tengfei.lee@qq.com QQ:1226369586 Blog:http://blog.csdn.net/li_tengfei 总结如下: 功能1:开始游戏 功能2:暂停游戏 功能3:重新开始游戏 功能4:控制方向
分析(OOA) 分析,即对游戏进行面向对象的建模,要正确的分析问题,必须对你要完成的需求有深刻的认识和理解。思考的主要问题是:本游戏存在哪些对象?对象有哪些特性?哪些对象与哪些对象有关?其关系是什么? 北京领航致远科技有限公司 http://www.leadfar.org
作者:李腾飞 e-mail:tengfei.lee@qq.com QQ:1226369586 Blog:http://blog.csdn.net/li_tengfei 设计(OOD) 设计是为实现服务的,你必须清楚如何实现,才能进行正确的设计,设计阶段思考的主要问题是: 1、 细化各个对象的属性,为了实现的便利,为了更好的复用等等各种目标,充分利用面向对象中的相关概念 2、 在完成各种功能的过程中,每个对象应该负责什么(职责分配)? 3、 每个对象的职责如何完成? a) 一般需要思考对象需要与哪些其它的对象进行什么样的交互以便完成某个职责
Android SDK 示例程序贪吃蛇详解
转载
Snake也是一个经典游戏了,Nokia蓝屏机的王牌游戏之一。
Android SDK 1.5就有了它的身影。
我们这里就来详细解析一下Android SDK Sample中的Snake工程。
本工程基于SDK 2.3.3版本中的工程,路径为:%Android_SDK_HOME% /samples/android-10/Snake
一、Eclipse工程
通过File-New Project-Android-Android Project,选择“Create project from existing sample”创建自己的应用SnakeAndroid,如下图:
运行效果如下图:
二、工程结构和类图
其实Snake的工程蛮简单的,源文件就三个:Snake.java SnakeView.java TileView.java。
Snake 类是这个游戏的入口点,TitleView类进行游戏的绘画,SnakeView类则是对游戏控制操作的处理。
Coordinate,RefreshHandler是2个辅助类,也是SnakeView类中的内部类。
其中,Coordinate是一个点的坐标(x,y),RefreshHandler将RefreshHandler对象绑定某个线程并给它发送消息。
如下图:
任何游戏都需要有个引擎来推动游戏的运行,最简化的游戏引擎就是:在一个线程中While 循环,检测用户操作,对用户的操作作出反应,更新游戏的界面,直到用户退出游戏。
在Snake这个游戏中,辅助类RefreshHandler继承自Handler,用来把RefreshHandler与当前线程进行绑定,从而可以直接给线程发送消息并处理消息。
注意一点:Handle对消息的处理都是异步。
RefreshHandler在Handler的基础上增加sleep()接口,用来每隔一个时间段后给当前线程发送一个消息。
handleMessage()方法在接受消息后,根据当前的游戏状态重绘界面,运行机制如下:
这比较类似定时器的概念,在特定的时刻发送消息,根据消息处理相应的事件。
update()与sleep()间接的相互调用就构成了一个循环。
这里要注意:mRedrawHandle绑定的是Avtivity 所在的线程,也就是程序的主线程;另外由于sleep()是个异步函数,所以update()与sleep()之间的相互调用才没有构成死循环。
最后分析下游戏数据的保存机制,如下:
这里考虑了Activity的生命周期:如果用户在游戏期间离开游戏界面,游戏暂停;或者由于内存比较紧张,Android关闭游戏释放内存,那么当用户返回游戏界面的时候恢复到上次离开时的界面。
三、源码解析
详细解析下源代码,由于代码量不大,以注释的方式列出如下:
3、TileView.java
四、工程文件下载
为了方便大家阅读,可以到如下地址下载工程源代码:
/f/14312223.html
五、小结及下期预告:
本次详细解析了Android SDK 自带Sample——Snake的结构和功能。
下次将会把这个游戏移植到J2ME平台上,并且比较Android和J2ME的区别和相通之处,让从事过J2ME开发的朋友对Android开发有个更加直观的认识。