Android围住神经猫的实现

2016年3月2日 会当凌绝顶,一览众山小。

为期三天的围住神经猫极简版已经出炉,虽说github或者其他博客已经吧这个简单的小项目写的很详细了,但我还是忍不住再扯一篇。一来为了加深理解,二来也给自己留个学习回忆,毕竟这是我的第一个完整的小游戏项目嘛。

下面我就按照我忍为比较好理解的思路来把整个项目重新整理一遍,期待可以和大家一起学习讨论。

功能预览

原版游戏项目预览:

围住神经猫原版游戏预览 本人的精简版:

我的精简项目预览

游戏玩法: 点击灰色的点设置红色的路障,每点击一次神经猫(橙色)都会移动一次,如果神经猫到达边界游戏失败,若围住了神经猫,则游戏胜利。

元素定义

由图中可以看出的,游戏的元素大致为10行10列的点阵,我们首先建立Dot类,然后建立Dot数组完成这个点阵。 Dot属性分析: 游戏中需要在背景图片上画出这些元素,所以他们仅仅通过数组下标进行区分是不合理的,为了找到他们在画板上的位置,我们就要给他们添上x,y坐标 其次,每个Dot都应该有着三种状态: 神经猫可走的状态 STATE_ON 神经猫不可走的路障状态 STATE_OFF 以及神经猫所处的状态 STATE_IN 我们设置对应的颜色为 ON_GRAY 灰色 OFF_RED红色 IN_ORANGE橙色 最后给对应的属性配置set和get方法。

Dot 类:

建立好这些点,我们要对游戏背景进行初始化,我们不能在通过activity_main.xml进行设置。 这时我首先想到view,但是很不幸,只有UI线程才能修改UI,如果使用view,我们将频繁的在线程间通信,这无疑加大了代码的复杂度和线程阻塞的可能性。 这时我们就需要游戏开发的常客:SurfaceView

SurfaceView

View必须在UI线程更新画面,而surfaceView是在一个新起的单独线程中重新绘制画面。这是两者的根本区别。 要想实现surfaceview 首先要继承surfaceview类,并实现SurfaceView.CallBack接口。 SurfaceVIew详解:http://www.360doc.com/content/13/0103/14/7724936_257842268.shtml

创建视图类

创建PlayGround类并继承SurfaceView。 该类主要实现游戏界面的绘制,游戏逻辑的实现。

Callback的三个方法:

surfaceCreated() Surface第一次创建后会立即调用该函数。 程序可以在该函数中做些和绘制界面相关的初始化工作, 一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。 surfaceChanged() 当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。 surfaceDestroyed() 当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface了,一般在该函数中来清理使用的资源。

为了方便检查程序的执行顺序,我习惯在每个方法上加上Log。

建立好后,我们为Activity设置

初始化游戏

在初始化数组时,让我们首先看一张数组下标和点坐标关系的图

蓝色为数组下标 黑色为坐标 由图中可知,点的坐标和数组下标刚好相反 例如dots[0][1]坐标为(1,0)。

我有一个想把什么代码都放入方法的毛病,不知是好是坏,这里为了方便后面代码的理解,我就把数组的初始化单独的放在initDots方法中了。

定义数组的长度final:

初始化数组

为了方便赋值state,我们可以先将所有元素都设置为灰色,然后指定橙色神经猫的位置,最后在已经变成灰色的点上随机出15个红色路障。 为这个数组的所有元素赋予属性STATE_ON:

定义路障数量:

随机路障:

再初始化神经猫之前,为了方便使用坐标引用对应的数组,建立方法

初始化神经猫:

初始化游戏: 每次重新开始游戏,都要调用该方法,重新初始化时,没必要重新初始化数组,只需改变数组中每个元素的STATE就好了,所以我们将initDots放在playground的构造函数时,而把其他三个初始化函数放入initGame中。 记住要按顺序调用函数。

数组元素的属性都配置好了,让我们测试一下!

在initGame后调用这个方法,检查一下初始化是否正确!

接下来就可以使用canves和paint进行绘制了!

元素的绘制

首先我们要根据屏幕的尺寸来确定点的半径。 共有两种实现方案。 1> 在MainActivity中获取屏幕尺寸

2> 第二种方法在callback的surfaceChanged的方法的第二个参数width(屏幕宽度)巧妙地获取点的直径

有了点的直径,我们就可以进行绘制了!

redraw方法

思考: 我们要根据点的属性的不同二给他们绘制不同的颜色,所以,优先考虑使用switch语句。 在游戏中,奇数行的起始位置显然比偶数行的起始位置大一个半径,我们可以使用偏移值来解决这个问题,当为偶数行时,偏移值为0,不骗移,如果为偶数时,偏移值为半径。

切记,不能在initGame后直接调用redraw方法,这样会使canvas对象为null 因为,如果surfaceCreated没有被调用就lockCanves,就会返回空,需要先创建surface才能使用canves绘制,如果没有surface,就永远不会有canves。

然后在callback方法中调用该方法,初始化游戏界面

响应用户的点击

当用户点击灰色的点时,灰色变为红色的路障,神经猫移动一次。 用户点击点阵以外的背景,进行游戏初始化。 用户点击其他点不做处理。 通过判断用户点击的坐标所落得位置,来做相应的颜色处理。 要想响应用户的点击,首先要实现OnTouchListener 并 重写OnTouch方法。

判断用户点击了哪一个元素,并作出相应的处理:

move()方法

我们通过返回cat到边缘的距离或障碍物的距离,来选出最优路径

getDistance

由图知,神经猫具有6个行走方向,我给他们设置了1-6编号

神经猫的行走方向

如果该方向处于边缘,返回1 如果该方向上没有障碍物,返回正数 如果有返回负数

移动cat到dot点:

判断一点是否在边界:

根据方向获取cat某一方向上的相邻点:

getDistance 获取该方向上的距离

判断玩家输赢:

move 根据距离选择最佳路径:

源码网上一大堆,我就不上传了,欢迎大家指出错误或提出建议.........

最后更新于

这有帮助吗?