贪吃蛇是一款非常经典的游戏,这些经典游戏给我们的童年添加了不少乐趣,今天開始我们来一步一步的在Android设备上实现一款贪吃蛇游戏,我也是第一次写这个游戏,有可能会写错,或者走弯路,可是终于希望能有一个好的结果,接下来我们一起来一步步的摸着石头开发吧。

一、建立一个project

二、自己定义View(贪吃蛇界面)

package com.example.crazysnake;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View; public class MySnake extends View {
private Paint paint;
private RectF rect; public MySnake(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
rect = new RectF();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
rect.set(50, 50, 90, 90);
paint.setColor(Color.RED);
canvas.drawRect(rect, paint);
} }

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.example.crazysnake.MySnake
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

执行效果:

我们在界面上绘制了一个小方块,这个就是我们完毕贪吃蛇的基础(就像我们要盖一座大楼的砖一样重要)

三、画一条彩蛇

先创建一个方块对象

package com.example.crazysnake;

public class Box {
private int x;
private int y; public Box(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}

绘制一排方块

package com.example.crazysnake;

import java.util.ArrayList;
import java.util.List; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View; public class MySnake extends View {
private Paint paint;
private RectF rect; private int boxSize = 30; private List<Box> boxs = new ArrayList<Box>(); private static final int[] colors = {
Color.RED,
Color.BLUE,
Color.GREEN,
Color.YELLOW
}; public MySnake(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
rect = new RectF();
initData();
} private void initData(){
Box box;
for(int i=0; i<10; i++){
box = new Box(i*boxSize, 0);
boxs.add(box);
}
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(int i=0; i<boxs.size(); i++){
paint.setColor(colors[i % colors.length]);
rect.set(boxs.get(i).getX(), boxs.get(i).getY(), boxs.get(i).getX() + boxSize, boxSize);
canvas.drawRect(rect, paint);
}
}
}

四、让这条彩蛇移动

重写onTouchEvent方法
	@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("onTouch");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_UP:
float disX = event.getX() - mDownX;
float disY = event.getY() - mDownY;
System.out.println("disX = " + disX);
System.out.println("dixY = " + disY);
if(Math.abs(disX) > Math.abs(disY)){
if(disX > 0){
System.out.println("right");
move(Derectory.RIGHT);
}else{
move(Derectory.LEFT);
}
}else{
if(disY > 0){ }else{ }
}
break;
}
return true;
}

move方法来依据方向移动

	private void move(Derectory derectory){
Box box;
int bs = 0;
switch (derectory) {
case LEFT:
case TOP:
bs = - boxSize;
break;
case RIGHT:
case BOTTOM:
bs = boxSize;
break;
} if(derectory == Derectory.LEFT || derectory == Derectory.RIGHT){
for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setX(box.getX() + bs);
}
}else{
for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setY(box.getY() + bs);
}
}
invalidate();
}

上面代码中我们没有控制边界,须要加入推断边界条件的代码。

五、让蛇自己主动跑,我们来控制它

启动一个线程了让蛇自己主动跑
	private class SnakeThread extends Thread{
private boolean stoped = false;
@Override
public void run() {
while(!stoped){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
move();
postInvalidate();
}
}
}

所有代码例如以下:

package com.example.crazysnake;

import java.util.ArrayList;
import java.util.List; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View; public class MySnake extends View {
private Paint paint;
private RectF rect; private int boxSize = 30; private SnakeThread snakeThread; private List<Box> boxs = new ArrayList<Box>(); private static final int[] colors = {
Color.RED,
Color.BLUE,
Color.GREEN,
Color.YELLOW
}; private enum Derectory{
LEFT,
RIGHT,
TOP,
BOTTOM;
} private Derectory currentDerect = Derectory.RIGHT; public MySnake(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
rect = new RectF();
initData();
startThread();
} public void startThread(){
if(snakeThread == null){
snakeThread = new SnakeThread();
snakeThread.start();
}
} private void initData(){
Box box;
for(int i=0; i<10; i++){
box = new Box(i*boxSize, 0);
boxs.add(box);
}
} private float mDownX;
private float mDownY;
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("onTouch");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_UP:
float disX = event.getX() - mDownX;
float disY = event.getY() - mDownY;
System.out.println("disX = " + disX);
System.out.println("dixY = " + disY);
if(Math.abs(disX) > Math.abs(disY)){
if(disX > 0){
currentDerect = Derectory.RIGHT;
}else{
currentDerect = Derectory.LEFT;
}
}else{
if(disY > 0){
currentDerect = Derectory.BOTTOM;
}else{
currentDerect = Derectory.TOP;
}
}
break;
}
return true;
} private class SnakeThread extends Thread{
private boolean stoped = false;
@Override
public void run() {
while(!stoped){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
move();
postInvalidate();
}
}
} private void move(){
Box box;
if(boxs.get(0).getX() - boxSize < 0) {
currentDerect = Derectory.RIGHT;
}
if(boxs.get(boxs.size() - 1).getX() + 2 * boxSize > getWidth()){
currentDerect = Derectory.LEFT;
}
switch (currentDerect) {
case LEFT: for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setX(box.getX() - boxSize);
}
break;
case RIGHT: for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setX(box.getX() + boxSize);
}
break;
case TOP: break;
case BOTTOM: break;
}
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(int i=0; i<boxs.size(); i++){
paint.setColor(colors[i % colors.length]);
rect.set(boxs.get(i).getX(), boxs.get(i).getY(), boxs.get(i).getX() + boxSize, boxSize);
canvas.drawRect(rect, paint);
}
}
}

今天先到这里吧,明天继续......^-^

是男人就下100层【第四层】——Crazy贪吃蛇(1)的更多相关文章

  1. 是男人就下100层【第四层】——Crazy贪吃蛇(2)

    在上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(1)>中我们让贪吃蛇移动了起来,接下来我们来实现让贪吃蛇能够绕着手机屏幕边线移动而且能够改变方向 一.加入状态并改动代码 首先我 ...

  2. 是男人就下100层【第四层】——Crazy贪吃蛇(3)

    上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(2)>实现了贪吃蛇绕着屏幕四周移动,这一篇我们来完成贪吃蛇的所有功能. 一.随机产生苹果 private void addAppl ...

  3. 超多经典 canvas 实例,动态离子背景、移动炫彩小球、贪吃蛇、坦克大战、是男人就下100层、心形文字等等等

    超多经典 canvas 实例 普及:<canvas> 元素用于在网页上绘制图形.这是一个图形容器,您可以控制其每一像素,必须使用脚本来绘制图形. 注意:IE 8 以及更早的版本不支持 &l ...

  4. Unity经典游戏教程之:是男人就下100层

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  5. HTML5游戏开发_是男人就下100层

    项目流程 市场调研(可行性分析)--> 可行性报告书  需求分析师.客户经理 需求分析--> 需求说明书  项目经理.需求分析师 概要设计--> 概要设计说明书(ER图, UML)  ...

  6. Cocos2d-x 版本小游戏 《是男人就下100层》 项目开源

    这个是很久就开始动手写的一个小游戏了,直到最近才把它收尾了,拖拖拉拉的毛病总是很难改啊. 项目是基于 cocos2d-x v2.2 版本 ,目前只编译到了 Win8 平台上,并且已经上传到了商店,支持 ...

  7. 『HTML5挑战经典』是英雄就下100层-开源讲座(二)危险!英雄

    本篇为<『HTML5挑战经典』是英雄就下100层-开源讲座>第二篇,需要用到开源引擎lufylegend,可以到这里下载: 下载地址:http://lufylegend.googlecod ...

  8. 『HTML5挑战经典』是英雄就下100层-开源讲座(一)从天而降的英雄

    是英雄就下100层是一款经典的手机小游戏,以前是在诺基亚手机上十分有名.今天我们就用HTML5和lufylegend一步步地实现它. 一,准备工作 首先,你需要下载lufylegend,下载地址如下: ...

  9. gdufe1538-是男人就上100层-(三维bfs)

    Problem Description: 桐老爷和UGO终于来到了名为“是男人就上一百层的塔”的下面,听说大祭司在第100层沉睡.为了题目需要,我把这个塔的层数随机打乱,层数的话大家就忘了前面的100 ...

随机推荐

  1. 实现一个简单的boot

    1.汇编语言.分别汇编器和链接as86和ld86.码如下面: .globl begtext,begdata,begbss,endtext,enddata,endbss .text begtext: . ...

  2. Ehcache BigMemory: 摆脱GC困扰(转)

    问题 使用java开源项目经常需要调优jvm,以优化gc.对于gc,如果对象都是短时对象,那么jvm相对容易优化,假如碰上像solr使用自带java cache的项目,那么gc严重受限于cache,因 ...

  3. SQL Server 2005------函数

    原文:SQL Server 2005------函数 SQL Server 2005支持用户自定义函数和内置系统函数,根据返回值类型又分为标量函数和表值函数. 1.标量函数标量函数:返回单个数据值,返 ...

  4. error while loading shared libraries: libpthread.so.0: cannot open shared object file: No such file

    安装rac10g,出现例如以下错误: [root@rac2 oracle]# /u01/product/crs/root.sh WARNING: directory '/u01/product' is ...

  5. extjs_09_定义自己的页面组件

    1.项目截图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWRhbV93enM=/font/5a6L5L2T/fontsize/400/fill/I0J ...

  6. 网站的SEO以及它和站长工具的之间秘密(转)

    博客迁移没有注意 URL 地址的变化,导致百度和 google 这两只爬虫引擎短时间内找不到路.近段时间研究了下国内最大搜索引擎百度和国际最大搜索引擎google的站长工具,说下感受. 百度的站长工具 ...

  7. Java依据Url下载图片

    package com.ronniewang.downloadpicture; import java.io.DataInputStream; import java.io.File; import ...

  8. 金蝶K3无法创建数据库,请查看该文件夹的错误的解决方法。

    无法创建数据库! 检查你的文件夹C:\XXX\DATA是否存在.并且该系统是不低,或SQL Server服务的启动用户不具备<K3ERP\DBFILE>文件夹的写权限.请改动Windows ...

  9. [cocos2dx注意事项009]试用quick-cocos2dx-2.2.4

    quick-cocos2d-x 在中国站http://quick.cocoachina.com/?page_id=40,用他们自己的话说:quick-cocos2d-x(后文简称 quick)与 co ...

  10. Web Api 2, Oracle and Entity Framework

    Web Api 2, Oracle and Entity Framework I spent about two days trying to figure out how to expose the ...