1、概述
在Android SurfaceView实战 带你玩转flabby bird (上)中,我们完成了在游戏所需的所有的元素的绘制,包括 Bird鸟、 Floor地板、Pipe 管道 、背景图以及分数等。
本篇博客将在上篇的基本上,继续带领大家向我们的目标进发,那么问题来了,我们的目标是:
就是这个效果图了。
首先我们明确下,当然我们的状态与上图的差距:
1、我们的管道只有一个,现需要动态生成,以及动态移除;
2、我们的鸟静止,现需要默认下落,按下屏幕上升一段距离;
3、现需要,判断鸟在飞翔过程中与管道以及地面的接触情况,判断是否Gameover;
4、现需要,当鸟每穿过一个管道的时候,我们能够进行计分+1 ;
ok,明确了目标~~~
那么首先,根据上述,我们发现我们的游戏缺少一个什么?
嗯,是状态,我们得知道游戏什么时候正在运行,什么时候准备运行,什么时候GameOver吧。所以引入一个枚举变量:
|
/** * 游戏的状态 * * @author zhy * */ private enum GameStatus { WAITING, RUNNING, OVER } |
1、默认情况下,是WAITING状态,屏幕静止,上面就一只静止的鸟~~
2、当用户触摸屏幕时:进入RUNNING状态,游戏开始根据用户的触摸情况进行交互;
3、当鸟触碰到管道或者落到地上,那么进入GAMEOVER状态,OVER时,如果触碰的是管道,则让鸟落到地上以后,立即切换为WAITING状态。
好了,这样,我们的三个状态就搞定了~~这才像个游戏么~
有了状态 ,我们再考虑如何处理用户交互,我们的交互主要就是触摸了,那么我们去重写View的onTouchEvent方法即可。
我们在onTouchEvent里面,根据用户的触摸游戏的状态、一些变量等;改变了的变量,会在绘制的时候进行体现,这样才形成了交互效果。
然后呢?为了我们代码的清晰,我们本来在线程中只有一个draw()方法,现在我们增加一个方法:logic();处理在游戏过程中分数的计算、管道的生成移除等。
这样可以把逻辑分开,logic专心做一些逻辑上的事,draw只管绘制;
说了这么多,如果你木有消化,没事,下面我们开始进入代码阶段了~~
2、动态生成和移除管道
首先我们增加一个mStatus变量:private GameStatus mStatus = GameStatus.WAITING;
然后添加logic方法以及复写onTouchEvent方法。
经过筛检后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
public class CopyOfGameFlabbyBird extends SurfaceView implements Callback, Runnable { //省略了一些代码 private enum GameStatus { WAITTING, RUNNING, STOP; } /** * 记录游戏的状态 */ private GameStatus mStatus = GameStatus.WAITTING; /** * 触摸上升的距离,因为是上升,所以为负值 */ private static final int TOUCH_UP_SIZE = -16; /** * 将上升的距离转化为px;这里多存储一个变量,变量在run中计算 * */ private final int mBirdUpDis = Util.dp2px(getContext(), TOUCH_UP_SIZE); private int mTmpBirdDis; /** * 鸟自动下落的距离 */ private final int mAutoDownSpeed = Util.dp2px(getContext(), 2); /** * 处理一些逻辑上的计算 */ private void logic() { switch (mStatus) { case RUNNING: // 管道移动 for (Pipe pipe : mPipes) { pipe.setX(pipe.getX() - mSpeed); } // 更新我们地板绘制的x坐标,地板移动 mFloor.setX(mFloor.getX() - mSpeed); break; case STOP: // 鸟落下 break; default: break; } } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) ߺ本上,继续带领大家向我们的目标进发,那么问题来了,我们的目标是:
就是这个效果图了。
首先我们明确下,当然我们的状态与上图的差距:
1、我们的管道只有一个,现需要动态生成,以及动态移除;
2、我们的鸟静止,现需要默认下落,按下屏幕上升一段距离;
3、现需要,判断鸟在飞翔过程中与管道以及地面的接触情况,判断是否Gameover;
4、现需要,当鸟每穿过一个管道的时候,我们能够进行计分+1 ;
ok,明确了目标~~~
那么首先,根据上述,我们发现我们的游戏缺少一个什么?
嗯,是状态,我们得知道游戏什么时候正在运行,什么时候准备运行,什么时候GameOver吧。所以引入一个枚举变量:
|
/** * 游戏的状态 * * @author zhy * */ private enum GameStatus { WAITING, RUNNING, OVER } |
1、默认情况下,是WAITING状态,屏幕静止,上面就一只静止的鸟~~
2、当用户触摸屏幕时:进入RUNNING状态,游戏开始根据用户的触摸情况进行交互;
3、当鸟触碰到管道或者落到地上,那么进入GAMEOVER状态,OVER时,如果触碰的是管道,则让鸟落到地上以后,立即切换为WAITING状态。
好了,这样,我们的三个状态就搞定了~~这才像个游戏么~
有了状态 ,我们再考虑如何处理用户交互,我们的交互主要就是触摸了,那么我们去重写View的onTouchEvent方法即可。
我们在onTouchEvent里面,根据用户的触摸游戏的状态、一些变量等;改变了的变量,会在绘制的时候进行体现,这样才形成了交互效果。
然后呢?为了我们代码的清晰,我们本来在线程中只有一个draw()方法,现在我们增加一个方法:logic();处理在游戏过程中分数的计算、管道的生成移除等。
这样可以把逻辑分开,logic专心做一些逻辑上的事,draw只管绘制;
说了这么多,如果你木有消化,没事,下面我们开始进入代码阶段了~~
2、动态生成和移除管道
首先我们增加一个mStatus变量:private GameStatus mStatus = GameStatus.WAITING;
然后添加logic方法以及复写onTouchEvent方法。
经过筛检后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
public class CopyOfGameFlabbyBird extends SurfaceView implements Callback, Runnable { //省略了一些代码 private enum GameStatus { WAITTING, RUNNING, STOP; } /** * 记录游戏的状态 */ private GameStatus mStatus = GameStatus.WAITTING; /** * 触摸上升的距离,因为是上升,所以为负值 */ private static final int TOUCH_UP_SIZE = -16; /** * 将上升的距离转化为px;这里多存储一个变量,变量在run中计算 * */ private final int mBirdUpDis = Util.dp2px(getContext(), TOUCH_UP_SIZE); private int mTmpBirdDis; /** * 鸟自动下落的距离 */ private final int mAutoDownSpeed = Util.dp2px(getContext(), 2); /** * 处理一些逻辑上的计算 */ private void logic() { switch (mStatus) { case RUNNING: // 管道移动 for (Pipe pipe : mPipes) { pipe.setX(pipe.getX() - mSpeed); } // 更新我们地板绘制的x坐标,地板移动 mFloor.setX(mFloor.getX() - mSpeed); break; case STOP: // 鸟落下 break; default: break; } } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) (isRunning)
{// 省略了一些代码
logic();
draw();
// 省略了一些代码
}
}
} | |