是男人就下100层【第四层】——Crazy贪吃蛇(2)
在上一篇《是男人就下100层【第四层】——Crazy贪吃蛇(1)》中我们让贪吃蛇移动了起来,接下来我们来实现让贪吃蛇能够绕着手机屏幕边线移动而且能够改变方向
一、加入状态并改动代码
public void postInvalidate(int left, int top, int right, int bottom) {
postInvalidateDelayed(0, left, top, right, bottom);
} /**
* Cause an invalidate to happen on a subsequent cycle through the event
* loop. Waits for the specified amount of time.
*
* @param delayMilliseconds the duration in milliseconds to delay the
* invalidation by
*/
public void postInvalidateDelayed(long delayMilliseconds) {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
if (mAttachInfo != null) {
Message msg = Message.obtain();
msg.what = AttachInfo.INVALIDATE_MSG;
msg.obj = this;
mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
}
} /**
* Cause an invalidate of the specified area to happen on a subsequent cycle
* through the event loop. Waits for the specified amount of time.
*
* @param delayMilliseconds the duration in milliseconds to delay the
* invalidation by
* @param left The left coordinate of the rectangle to invalidate.
* @param top The top coordinate of the rectangle to invalidate.
* @param right The right coordinate of the rectangle to invalidate.
* @param bottom The bottom coordinate of the rectangle to invalidate.
*/
public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
int right, int bottom) { // We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
if (mAttachInfo != null) {
final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
info.target = this;
info.left = left;
info.top = top;
info.right = right;
info.bottom = bottom; final Message msg = Message.obtain();
msg.what = AttachInfo.INVALIDATE_RECT_MSG;
msg.obj = info;
mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
}
}
从上面源代码中我们能够看到最后一句代码mAttachInfo.mHandler.sendMessageDelayed(msg, delayMillisecods),原来也是通过Handler来实现界面刷新的。既然是这样我们就将我们的代码改动例如以下:
class RefreshHandler extends Handler{
@Override
public void handleMessage(Message msg) {
MySnake.this.update();
MySnake.this.invalidate(); } public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
定义了游戏中的四种状态
private enum State{
READY, //就绪
PAUSE, //暂停
RUNNING, //执行
LOSE //失败
}
private void update(){
if(currentState == State.RUNNING){
move();
mRefreshHandler.sleep(1000);
}
}
case LEFT:
/*for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setX(box.getX() - boxSize);
} */
boxs.add(0, new Box(boxs.get(0).getX() - boxSize, 0));
boxs.remove(boxs.size() - 1);
break;
case RIGHT: /* for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setX(box.getX() + boxSize);
} */
boxs.add(new Box(boxs.get(boxs.size() - 1).getX() + boxSize, 0));
boxs.remove(0);
break;
我们不用遍历每个方块来实现蛇的移动,我们仅仅须要去改变蛇首和蛇未就可以实现。
改动后的MySnake.java文件
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.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* CSDN博客:http://blog.csdn.net/dawanganban
* @author 阳光小强
*/
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 enum State{
READY, //就绪
PAUSE, //暂停
RUNNING, //执行
LOSE //失败
} private Derectory currentDerect = Derectory.RIGHT;
private State currentState = State.PAUSE; private RefreshHandler mRefreshHandler = new RefreshHandler();
class RefreshHandler extends Handler{
@Override
public void handleMessage(Message msg) {
MySnake.this.update();
MySnake.this.invalidate(); } public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
} 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 update(){
if(currentState == State.RUNNING){
move();
mRefreshHandler.sleep(1000);
}
} 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){
if(currentState != State.RUNNING){
currentState = State.RUNNING;
update();
}
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);
} */
boxs.add(0, new Box(boxs.get(0).getX() - boxSize, 0));
boxs.remove(boxs.size() - 1);
break;
case RIGHT: /* for(int i=0; i<boxs.size(); i++){
box = boxs.get(i);
box.setX(box.getX() + boxSize);
} */
boxs.add(new Box(boxs.get(boxs.size() - 1).getX() + boxSize, 0));
boxs.remove(0);
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);
}
}
}
二、实现绕手机边界移动的贪吃蛇

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.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* CSDN博客:http://blog.csdn.net/dawanganban
* @author 阳光小强
*/
public class MySnake extends View {
private Paint paint;
private Paint textPaint;
private RectF rect; private static int boxSize = 40; private static int xMaxBoxCount; //x轴方向最多的box数量
private static int yMaxBoxCount; //y轴方向最多的box数量 private List<Box> boxs = new ArrayList<Box>(); private static final int[] colors = {
Color.RED,
Color.BLUE,
Color.GRAY,
Color.YELLOW
}; private enum Derectory{
LEFT,
RIGHT,
TOP,
BOTTOM;
} private enum State{
READY, //就绪
PAUSE, //暂停
RUNNING, //执行
LOSE //失败
} private Derectory currentDerect = Derectory.LEFT;
private State currentState = State.READY; private RefreshHandler mRefreshHandler = new RefreshHandler();
class RefreshHandler extends Handler{
@Override
public void handleMessage(Message msg) {
MySnake.this.update();
MySnake.this.invalidate(); } public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
} public MySnake(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
textPaint = new Paint();
textPaint.setColor(Color.RED);
textPaint.setTextSize(80);
rect = new RectF();
initData();
} private void update(){
if(currentState == State.RUNNING){
move();
mRefreshHandler.sleep(150);
}
} private void initData(){
Box box;
for(int i=5; i<10; i++){
box = new Box(i, 0);
boxs.add(box);
}
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
xMaxBoxCount = (int) Math.floor(w / boxSize);
yMaxBoxCount = (int) Math.floor(h / boxSize);
} 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{
if(currentState != State.RUNNING){
currentState = State.RUNNING;
currentDerect = Derectory.LEFT;
update();
} }
}else{
if(disY > 0){
// currentDerect = Derectory.BOTTOM;
}else{
// currentDerect = Derectory.TOP;
}
}
break;
}
return true;
} private void move(){
Box box;
if(currentDerect == Derectory.LEFT && boxs.get(0).getX() <= 0){
currentDerect = Derectory.BOTTOM;
}
if(currentDerect == Derectory.BOTTOM && boxs.get(0).getY() >= yMaxBoxCount -1){
currentDerect = Derectory.RIGHT;
}
if(currentDerect == Derectory.RIGHT && boxs.get(0).getX() >= xMaxBoxCount - 1){
currentDerect = Derectory.TOP;
}
if(currentDerect == Derectory.TOP && boxs.get(0).getY() <= 0){
currentDerect = Derectory.LEFT;
}
switch (currentDerect) {
case LEFT:
boxs.add(0, new Box(boxs.get(0).getX() - 1, boxs.get(0).getY()));
boxs.remove(boxs.size() - 1);
break;
case RIGHT:
boxs.add(0, new Box(boxs.get(0).getX() + 1, boxs.get(0).getY()));
boxs.remove(boxs.size() - 1);
break;
case TOP:
boxs.add(0, new Box(boxs.get(0).getX(), boxs.get(0).getY() - 1));
boxs.remove(boxs.size() - 1);
break;
case BOTTOM:
boxs.add(0, new Box(boxs.get(0).getX(), boxs.get(0).getY() + 1));
boxs.remove(boxs.size() - 1);
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() * boxSize, boxs.get(i).getY() * boxSize,
(boxs.get(i).getX() + 1) * boxSize, (boxs.get(i).getY() + 1) * boxSize);
canvas.drawRect(rect, paint);
}
if(currentState == State.READY){
canvas.drawText("请向左滑动", (xMaxBoxCount * boxSize - textPaint.measureText("请向左滑动")) / 2,
xMaxBoxCount * boxSize / 2, textPaint);
}
}
}
源代码下载说明:前一个版本号在GitHub上,这一版我将该项目上传到了CSDN的CODE上面,能够使用SVN或Git下载
CODE源代码下载地址:https://code.csdn.net/lxq_xsyu/crazysnake
是男人就下100层【第四层】——Crazy贪吃蛇(2)的更多相关文章
- 是男人就下100层【第四层】——Crazy贪吃蛇(3)
上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(2)>实现了贪吃蛇绕着屏幕四周移动,这一篇我们来完成贪吃蛇的所有功能. 一.随机产生苹果 private void addAppl ...
- 超多经典 canvas 实例,动态离子背景、移动炫彩小球、贪吃蛇、坦克大战、是男人就下100层、心形文字等等等
超多经典 canvas 实例 普及:<canvas> 元素用于在网页上绘制图形.这是一个图形容器,您可以控制其每一像素,必须使用脚本来绘制图形. 注意:IE 8 以及更早的版本不支持 &l ...
- Unity经典游戏教程之:是男人就下100层
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- 是男人就下100层【第四层】——Crazy贪吃蛇(1)
贪吃蛇是一款非常经典的游戏,这些经典游戏给我们的童年添加了不少乐趣,今天開始我们来一步一步的在Android设备上实现一款贪吃蛇游戏,我也是第一次写这个游戏,有可能会写错,或者走弯路,可是终于希望能有 ...
- HTML5游戏开发_是男人就下100层
项目流程 市场调研(可行性分析)--> 可行性报告书 需求分析师.客户经理 需求分析--> 需求说明书 项目经理.需求分析师 概要设计--> 概要设计说明书(ER图, UML) ...
- Cocos2d-x 版本小游戏 《是男人就下100层》 项目开源
这个是很久就开始动手写的一个小游戏了,直到最近才把它收尾了,拖拖拉拉的毛病总是很难改啊. 项目是基于 cocos2d-x v2.2 版本 ,目前只编译到了 Win8 平台上,并且已经上传到了商店,支持 ...
- 『HTML5挑战经典』是英雄就下100层-开源讲座(二)危险!英雄
本篇为<『HTML5挑战经典』是英雄就下100层-开源讲座>第二篇,需要用到开源引擎lufylegend,可以到这里下载: 下载地址:http://lufylegend.googlecod ...
- 『HTML5挑战经典』是英雄就下100层-开源讲座(一)从天而降的英雄
是英雄就下100层是一款经典的手机小游戏,以前是在诺基亚手机上十分有名.今天我们就用HTML5和lufylegend一步步地实现它. 一,准备工作 首先,你需要下载lufylegend,下载地址如下: ...
- gdufe1538-是男人就上100层-(三维bfs)
Problem Description: 桐老爷和UGO终于来到了名为“是男人就上一百层的塔”的下面,听说大祭司在第100层沉睡.为了题目需要,我把这个塔的层数随机打乱,层数的话大家就忘了前面的100 ...
随机推荐
- Error:Failed to resolve: com.afollestad:material-dialogs:
http://www.chenruixuan.com/archives/1068.html 背景: 同事把Android项目直接考给了我...我在Android Studio上运行,然后提示: Err ...
- loadClass和forName 的区别
类的加载方式 1.隐式加载:new 2.显式加载,loadClass,forName 等 loadClass 和 forName的区别 类的装载过程 1.加载:通过classLoader加载class ...
- sublime中项目无法添加文件夹
问题记录 mac中,使用vue init webpack project 后,在sublime中打开,但是添加新文件夹和删除,总提示没有权限, 然后用git提交吧 也不行,每次都要sudo 出现的提示 ...
- [LUOGU] P2704 炮兵阵地
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队. 一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), 也可能是平原(用"P&q ...
- 组管理命令--groupadd.groupmod.groupdel.gpasswd
添加用户组 格式 groupadd [参数] 组名 参数选项 -g GID:指定新组的GID,默认值是已有的最大的GID加1.-r:建立一个系统专用组,与-g不同时使用时,则分配一个1-499的GID ...
- bacula快速部署
快速部署: Server端:DD.SD.Monitor.Console均部署在Server上Client端:FD Server端部署:上传事先下载的源码包 tar xvf bacula-9.2.0.t ...
- nginx的配置和基本使用命令
配置文件基本说明 配置文件位置:/usr/local/nginx/conf/nginx.conf #设置用户群,nobody代表低权限用户 #user nobody; #工作衍生进程数,通常代表CPU ...
- POJ 1201 Intervals(差分约束 区间约束模版)
关于差分约束详情可阅读:http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html 题意: 给定n个区间[L,R], 每个区间至 ...
- Java学习之跳转语句
Java语言中提供3中跳转语句,分别是break语句.continue语句和return语句. break语句 可以用在switch语句中.在switch语句中,break语句用于中止下面的case语 ...
- mybatis动态sql foreach的用法
<select id="findUserByIds" parameterType="com.pojo.QueryVo" resultType=" ...