Android 贪食蛇
初级贪食蛇
文章目录
- 初级贪食蛇
- 效果展示:
- 界面设计
- 算法设计
- 游戏面板类
- 蛇身类
- 蛇类
- 方向类
- 主函数类
效果展示:
界面设计
游戏界面的设计布局我们采用“相对布局中嵌套线性布局”这样做的好处是界面整体对称性更强,游戏体验更佳。
用相对布局将游戏界面分成两部分,一部分为游戏展示界面,一部分为按钮控制界面。
这里的界面设计着重是按钮布局的界面,游戏展示界面将在算法设计中的游戏面板类中展开。
游戏展示界面我们需要调用游戏面板类的内容:
<com.example.sqltext.GamePanelandroid:id="@+id/gamePanel"android:layout_width="match_parent"android:layout_height="500dp" />
按钮控制界面则采用线性布局和相对布局相辅相成,使得整个界面规整,对称。我们将按钮控制界面分为三个部分,将开始游戏和结束游戏放于左边,方向控制居中处理,暂停和继续放于右边。
<LinearLayoutandroid:layout_below="@+id/gamePanel"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><LinearLayoutandroid:orientation="vertical"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"><Buttonandroid:id="@+id/start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="开始游戏" /><Buttonandroid:id="@+id/back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="退出游戏" /></LinearLayout><RelativeLayoutandroid:layout_width="0dp"android:layout_weight="3"android:layout_height="match_parent"><Buttonandroid:id="@+id/up"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="上"android:textStyle="bold" /><Buttonandroid:id="@+id/left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="左"android:layout_below="@+id/up"android:layout_toLeftOf="@+id/down"android:textStyle="bold" /><Buttonandroid:id="@+id/right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="右"android:layout_below="@+id/up"android:layout_toRightOf="@+id/down"android:textStyle="bold" /><Buttonandroid:id="@+id/down"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_below="@+id/up"android:text="下"android:textStyle="bold" /></RelativeLayout><LinearLayoutandroid:orientation="vertical"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"><Buttonandroid:id="@+id/Continue"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="继续游戏" /><Buttonandroid:id="@+id/Stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="暂停" /></LinearLayout></LinearLayout>
将按钮的布置尽量美观并且符合玩家习惯。
布局效果展示:
算法设计
界面的设计完成过后,现在需要进行算法的更新以及按钮的适配。
由繁入简,我们需要先将游戏面板的内容完善,再逐渐布局“贪食蛇”
游戏面板类
在这个类里,我们需要完成定义界面高度和宽度,蛇身的类调用,分数,速度,开始游戏,格子大小,活动范围,蛇长算法,食物坐标,方向,食物与蛇身重叠,蛇头位置,按键过快导致BUG等问题。
首先完成声明定义:
class GamePanel extends View implements View.OnTouchListener {public int wid,hei;//获得View的宽和高public ArrayList<SnackBody> body = new ArrayList<SnackBody>(); //蛇身public int score;//分数public int speed;//速度public boolean start;//开始游戏private static final int MAX_Height = 20;private static final int MAX_Width = 20; //活动范围20*20private int rectSize; //每一格子大小private int snackLength ;//蛇长private int foodX,foodY;//食物坐标private Random random;private Paint paint;private int direction; //方向private int eatSign; // 用于判断刷新下一个食物是否和蛇身重叠private Snack snack;private DirectiomThread left = new DirectiomThread(this,1);private DirectiomThread up = new DirectiomThread(this,2);private DirectiomThread right = new DirectiomThread(this,3);private DirectiomThread down = new DirectiomThread(this,4);private int itemX,itemY; //判断蛇头位置public int lastDirection;//限制过于快速按键吃掉自己BUGpublic GamePanel(Context context) { super(context); }public GamePanel(Context context, AttributeSet attributeSet){super(context,attributeSet);}
其次是初始化定义,将分数设为0,速度为100,蛇头方向,食物方向,蛇身长度都完成初始化定义。
public void init(){rectSize = wid/MAX_Width; score = 0; speed = 100;itemX = -1;itemY = -1;body.clear();snackLength= 0;random = new Random();paint = new Paint();paint.setAntiAlias(true);direction =3;lastDirection = 3;this.setWillNotDraw(false);}
然后完成画布的颜色分类,前期的准备工作就基本完成了:
protected void onDraw(Canvas canvas){//画布if (start){paint.setColor(Color.YELLOW); //食物颜色canvas.drawRect(foodX*rectSize,foodY*rectSize,foodX*rectSize+rectSize,foodY*rectSize+rectSize,paint);if (body.size()>0){paint.setColor(Color.BLUE); //头部颜色canvas.drawRect(body.get(0).getX()*rectSize,body.get(0).getY()*rectSize,body.get(0).getX()*rectSize+rectSize,body.get(0).getY()*rectSize+rectSize,paint);paint.setColor(Color.GREEN); //身体颜色for (int i=1;i<body.size();i++){canvas.drawRect(body.get(i).getX()*rectSize,body.get(i).getY()*rectSize,body.get(i).getX()*rectSize+rectSize,body.get(i).getY()*rectSize+rectSize,paint);}paint.setColor(Color.RED);paint.setTextSize(50);canvas.drawText("分数:" + score, wid-300, wid-20, paint); //分数}}}
如图,蓝色为蛇头,绿色为蛇身,黄色为食物,红色为分数提示。
为了后续蛇身移动,定义方向,还需要一个大小更改的定义:
protected void onSizeChanged(int w,int h,int oldw,int oldh){super.onSizeChanged(w,h,oldw,oldh);wid = w;hei = h;}
完成这些设置之后,我们开始写点击开始游戏后的算法:
点击开始游戏后,会自动向右边移动,蛇身位置会从newBody到newBody2;
public void startGame(){ //开始游戏init();start = true;SnackBody newBody = new SnackBody();newBody.setX(MAX_Width/2);newBody.setY(MAX_Height/2);SnackBody newBody2 = new SnackBody();newBody2.setX(MAX_Width/2-1);newBody2.setY(MAX_Width/2);body.add(newBody);body.add(newBody2);do {foodX = random.nextInt(MAX_Width-1);foodY = random.nextInt(MAX_Height-1);}while (foodX == newBody.getX() && foodY == newBody.getY());snack = new Snack(this);snack.start();}
游戏开始后,蛇体可由玩家控制,我们需要完成一个移动的算法:
public void move(int x,int y){ //移动itemX = body.get(0).getX()+x;itemY = body.get(0).getY()+y;if (itemX == foodX && itemY == foodY){eat();for (int i = body.size()-2;i>0;i--){body.get(i).setX(body.get(i-1).getX());body.get(i).setY(body.get(i-1).getY());}}else {for (int i = body.size() - 1; i > 0; i--) {body.get(i).setX(body.get(i - 1).getX());body.get(i).setY(body.get(i - 1).getY());}}body.get(0).setX(body.get(0).getX() + x);body.get(0).setY(body.get(0).getY() + y);}
贪食蛇的重点在于吃,吃了以后身体会加长:
每吃到一个食物,身体就会张长。将身体张长的数据增加到growbody数据类中。
public void eat(){ //吃score = score+10;snackLength++;do {eatSign = 0;foodX = random.nextInt(MAX_Height-1);foodY = random.nextInt(MAX_Width-1);for (int i = 0; i<body.size();i++){if (foodX == body.get(i).getX() && foodY == body.get(i).getY()){eatSign++;}}if (foodX == itemX && foodY == itemY)eatSign++;}while (eatSign>0);SnackBody growBody = new SnackBody();growBody.setX(body.get(body.size()-1).getX());growBody.setY(body.get(body.size()-1).getY());body.add(growBody);}
贪食蛇的死亡判定为撞到边界或者自己身体,此时游戏会结束。
public boolean hitOrBite(){ //碰到边界if (body.get(0).getX() < 0 || body.get(0).getX() >= 20|| body.get(0).getY() < 0 || body.get(0).getY() >= 20)return true;else {for (int i = body.size() - 1; i > 2; i--) {if (body.get(0).getX() == body.get(i).getX()&& body.get(0).getY() == body.get(i).getY())return true;}}return false;}public void dead() { }public int getDirection(){return direction;}public void setDirection(int direction) {this.direction = direction;}public int getScore() {return score;}
完成上面的算法,我们仅仅完成了游戏展示界面以及其算法。下面我们还要继续完善按钮控制的算法。
为防止BUG冲突,例如蛇头突然180°转头导致游戏结束。设置了以下规则:当蛇头为左边时候,不难按下右键,以此类推。
@Overridepublic boolean onTouch(View v, MotionEvent event) {if (v.getId() == R.id.left && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=3 ){left = new DirectiomThread(this,1);up.canRun = false;right.canRun = false;down.canRun = false;left.canRun = true;left.start();}}else if (v.getId() == R.id.left && event.getAction() == MotionEvent.ACTION_UP){left.canRun = false;}if (v.getId() == R.id.up && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=4 ){up = new DirectiomThread(this,2);up.canRun = true;right.canRun = false;down.canRun = false;left.canRun = false;up.start();}}else if (v.getId() == R.id.up && event.getAction() == MotionEvent.ACTION_UP){up.canRun = false;}if (v.getId() == R.id.right && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=1 ){right = new DirectiomThread(this,3);up.canRun = false;right.canRun = true;down.canRun = false;left.canRun = false;right.start();}}else if (v.getId() == R.id.right && event.getAction() == MotionEvent.ACTION_UP){right.canRun = false;}if (v.getId() == R.id.down && event.getAction() == MotionEvent.ACTION_DOWN){if (lastDirection !=2 ){down = new DirectiomThread(this,4);up.canRun = false;right.canRun = false;down.canRun = true;left.canRun = false;down.start();}}else if (v.getId() == R.id.right && event.getAction() == MotionEvent.ACTION_UP){down.canRun = false;}
规范了游戏规则后,还需设定开始游戏以及暂停,继续游戏的算法:
if (v.getId() == R.id.start && event.getAction() == MotionEvent.ACTION_UP && start==false){this.startGame();}if (v.getId() == R.id.Continue && event.getAction() == MotionEvent.ACTION_UP && start ==false){start = true;snack = new Snack(this);snack.start();}if (v.getId() == R.id.Stop && event.getAction() == MotionEvent.ACTION_UP){start = false;}return false;
如此,游戏面板类的内容大致完成,接下面是完善蛇身类,方向类,蛇类定义以及最后的主函数使用。
接下来这三类均为游戏面板类线程的子线程,为方便修改。
蛇身类
此类用来定义蛇身的位置信息:
自动完善get和set方法。
class SnackBody {private int x,y;public int getX() {return x;}public int getY() {return y;}public void setX(int x) {this.x = x;}public void setY(int y) {this.y = y;}
}
蛇类
此类用来定义蛇体本身的跟踪,调用游戏面板类的算法集合。
class Snack extends Thread {private GamePanel gamePanel; //声明地图public Snack(GamePanel gamePanel){this.gamePanel= gamePanel;} //声明蛇存在地图public void run(){ //处理的逻辑while (gamePanel.start){ //当点击开始try {long before = System.currentTimeMillis(); //开始前时间gamePanel.postInvalidate(); //调用gamePanellong after= System.currentTimeMillis(); //结束时间Thread.sleep((int)((20000/gamePanel.speed)-(after-before))); //蛇移动速度}catch (InterruptedException e){ //中断异常e.printStackTrace(); //追踪}switch (gamePanel.getDirection()){case 1: //选择左gamePanel.move(-1,0); //X轴向左移动一个像素,y轴不变gamePanel.lastDirection = 1; //最后一个位置为:左break;case 2: //选择上gamePanel.move(0,-1); // X轴不变,y轴向上移动一个像素gamePanel.lastDirection = 2; //最后一个位置为:上break;case 3: //选择右gamePanel.move(1,0); //X轴向右移动一个像素,y轴不变gamePanel.lastDirection = 3; //最后一个位置为:右break;case 4: //选择右gamePanel.move(0,1); // X轴不变,y轴向下移动一个像素gamePanel.lastDirection = 4; //最后一个位置为:下break;}if (gamePanel.hitOrBite()){ //撞到墙壁gamePanel.start = false; //结束游戏gamePanel.dead(); //蛇死亡continue;}}}
}
方向类
此类用来定义蛇的方向条件以及蛇的速度:
class DirectiomThread extends Thread{private GamePanel gamePanel;private int direction;public boolean canRun;public DirectiomThread(GamePanel gamePanel,int direction){this.gamePanel = gamePanel;this.direction = direction;}public void run(){while (canRun){gamePanel.setDirection(direction);try {Thread.sleep(10);}catch (InterruptedException e){e.printStackTrace();}}}
}
主函数类
在主函数中需要添加一段重要代码,该代码为调用游戏面板类进行游戏展示:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)gamePanel.getLayoutParams();gamePanel.setLayoutParams(params);params.width = width;params.height = width;
如此就能够完成贪食蛇的游戏展示
主函数完全代码:
public class game extends AppCompatActivity {private Button up,left,right,down;private Button start,back,Continue,Stop;private GamePanel gamePanel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_game);getSupportActionBar().hide();//隐藏标题栏getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏up = findViewById(R.id.up);left = findViewById(R.id.left);right = findViewById(R.id.right);down = findViewById(R.id.down);start = findViewById(R.id.start);back = findViewById(R.id.back);Continue = findViewById(R.id.Continue);Stop = findViewById(R.id.Stop);DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);int width = metrics.widthPixels;int height = metrics.heightPixels;gamePanel = findViewById(R.id.gamePanel);gamePanel.setBackgroundColor(Color.LTGRAY);RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)gamePanel.getLayoutParams();gamePanel.setLayoutParams(params);params.width = width;params.height = width;start.setOnTouchListener(gamePanel);Continue.setOnTouchListener(gamePanel);back.setOnTouchListener(gamePanel);Stop.setOnTouchListener(gamePanel);left.setOnTouchListener(gamePanel);right.setOnTouchListener(gamePanel);up.setOnTouchListener(gamePanel);down.setOnTouchListener(gamePanel);back.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(game.this,Main2.class);startActivity(intent);finish();}});}protected void onStart(){super.onStart();}protected void onStop(){super.onStop();}protected void onPause(){super.onPause();gamePanel.start = false;}protected void onResume() {super.onResume();}protected void onRestart() {super.onRestart();}protected void onDestroy() {super.onDestroy();}
}
大家也可以一起尝试开发出自己的贪食蛇小游戏哟
Android 贪食蛇相关推荐
- android贪食蛇详细教程实现加源码
转载请注明出处:http://blog.csdn.net/b2569449528/article/details/78475327 工作需要开发了一个贪食蛇apk预装到公司产品,共10关.包含了游戏得 ...
- 一个完整的嵌入式程序_【荐读】贪食蛇游戏的Android嵌入式系统设计
贪食蛇游戏的Android嵌入式系统设计 Design of Android Embedded-System for Greedy Snake Game 作者: 韩 中, 苟和平, 李 援:琼台师范学 ...
- linux终端贪吃蛇,分享|nSnake: 在Linux的终端上玩经典的贪食蛇游戏
你知道20世纪末的那些古老的诺基亚手机上最棒的东西是什么吗? 贪食蛇! 我以前在这个看似无聊但却让人上瘾的游戏上花费了大把的时间.在古老的诺基亚手机被智能手机取代的同时,贪食蛇也被另外的无聊但却令人上 ...
- [原]Console小技巧——Console版贪食蛇
这一篇是我的Console小技巧的最后一篇文章,以下是索引: 1.[原]Console小技巧--七彩输出 2.[原]Console小技巧--字符涂鸦 3.[原]Console小技巧--Console版 ...
- tomcat websock html5,websocket实战(4) websocket版贪食蛇游戏(tomcat官方自带)
通过前面3篇的阐述,相信可以构建一个简单的socket应用了.当然,也会遗漏了许多知识点,相信会在以后分享的实例中捎带说明下. 本文的主要是分析下tomcat官方自带的贪食蛇游戏.为什么选择分析这个项 ...
- java小程序贪吃蛇代码_微信小程序Demo之贪食蛇
原标题:微信小程序Demo之贪食蛇 差不多大半年前,笔者发布了一篇关于OC版贪食蛇开发的文章,时隔多月,微信小程序横空出世,于是闲来无事的我又写了一个小程序版. 01页面布局 关于小程序笔者就不做介绍 ...
- 【第三篇:利用ChatGPT编写贪食蛇小游戏】
好像现在最近对ChatGPT讨论越来越热,ChatGPT的出现应该会引发"一次新的社会变革",未来很多码农会失业啊!与其坐着被改变,不如尝试主动改变,我今天就利用ChatGPT编写 ...
- 原生js实现贪食蛇小游戏
先不多说先上图 下面是代码部分(这里你可以根据需要改变蛇头和身体还有食物的图片,然后默认的样式是使用纯颜色的如果没有更改我的背景图片的话------改这些图开始是想搞笑一下朋友哈哈哈,请不要在意哈), ...
- 使用C++设计贪食蛇小游戏
说明:所有代码均可在Visual Studio 2013上编译执行.并未测试在其它编译器上编译情况. 游戏规则 贪食蛇游戏要求玩家控制方向键(或WSAD键)来控制小蛇的前进方向,以使蛇吃掉面板上随即位 ...
最新文章
- vs连接mysql建一个表并增删查改_VS连接SQL Server数据库,增删改查详细教程(C#代码)...
- 使用VC++6.0创建MFC对话框程序
- php javabean对象,Struts2 bean标签:创建并示例化一个JavaBean对象
- 局部特征(3)——SURF特征总结
- python输出字母金字塔可以输入字母和行数的_python实现输入任意一个大写字母生成金字塔的示例...
- [ActiveRecord] 之ActiveRecordMediator
- 法国 计算机 转专业,在法国留学怎样换专业
- android屏幕适配教程,Android屏幕适配方案,android屏幕适配
- 计算机组成原理 第七章 输入输出系统
- React Native悬浮效果组件
- 堆——神奇的优先队列(上)
- Eclipse—在Eclipse中如何发布创建的JavaWeb工程
- C#中各种字符类型的转化
- python字典快速一览
- python 导出依赖包
- 制作Win10PE启动盘
- lvgl 主要文件目录树
- 2008最火爆的十大网络流行语
- 变限积分性质的总结笔记
- DELL G7 重装win10系统