Android实例剖析笔记(五)
2011-08-28 23:34 狼人:-) 阅读(184) 评论(0) 编辑 收藏 举报游戏暂停/继续机制
由于原来的代码中在游戏运行时没有提供控制选项(比如暂停/继续),因此除非你死了,否则只能玩到底。我这里对代码进行一些修改,加入一个Option Menu来提供暂停/继续机制。
首先加入一个变量记录游戏当前状态
private int mState = SnakeView.READY;
然后重载onCreateOptionsMenu函数,创建一个控制菜单项,并对其进行处理,提供暂停/继续机制。
/*
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
* @Author:phinecos
* @Date:2009-08-28
*/
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case MENU_CONTROL:
{
if (mState == SnakeView.PAUSE)
{//此前状态是"停止",则转为"运行"
mState = SnakeView.RUNNING;
mSnakeView.setMode(SnakeView.RUNNING);
item.setIcon(android.R.drawable.ic_media_pause).setTitle(R.string.cmd_pause);
}
else if(mState == SnakeView.RUNNING)
{//此前状态是"运行",则转为“暂停"
mState = SnakeView.PAUSE;
mSnakeView.setMode(SnakeView.PAUSE);
item.setIcon(android.R.drawable.ic_media_play).setTitle(R.string.cmd_run);
}
else if(mState == SnakeView.READY)
{//此前是"初始状态",则转为"运行"
mState = SnakeView.RUNNING;
}
return true;
}
}
return super.onOptionsItemSelected(item);
}
/*
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
* @Author:phinecos
* @Date:2009-08-28
*/
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
menu.add(0, MENU_CONTROL, 0, R.string.cmd_pause).setIcon(android.R.drawable.ic_media_pause);
return true;
}
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
* @Author:phinecos
* @Date:2009-08-28
*/
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case MENU_CONTROL:
{
if (mState == SnakeView.PAUSE)
{//此前状态是"停止",则转为"运行"
mState = SnakeView.RUNNING;
mSnakeView.setMode(SnakeView.RUNNING);
item.setIcon(android.R.drawable.ic_media_pause).setTitle(R.string.cmd_pause);
}
else if(mState == SnakeView.RUNNING)
{//此前状态是"运行",则转为“暂停"
mState = SnakeView.PAUSE;
mSnakeView.setMode(SnakeView.PAUSE);
item.setIcon(android.R.drawable.ic_media_play).setTitle(R.string.cmd_run);
}
else if(mState == SnakeView.READY)
{//此前是"初始状态",则转为"运行"
mState = SnakeView.RUNNING;
}
return true;
}
}
return super.onOptionsItemSelected(item);
}
/*
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
* @Author:phinecos
* @Date:2009-08-28
*/
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
menu.add(0, MENU_CONTROL, 0, R.string.cmd_pause).setIcon(android.R.drawable.ic_media_pause);
return true;
}
修改后运行截图如下:
当然,这段代码还是有问题的,游戏刚开始时,必须先点击菜单确认,再按上方向键才能开始。(以后再来修改。。。)
穿墙贪食蛇
第二个修改是把这个普通的贪食蛇改成可以穿墙(呵呵,这样就可以不死了。。。)。想必要修改的就是撞墙检测那段代码?没错,就是下面这段!
// Collision detection
// For now we have a 1-square wall around the entire arena
if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2)|| (newHead.y > mYTileCount - 2))
{//撞墙
setMode(LOSE);
return;
}
// For now we have a 1-square wall around the entire arena
if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2)|| (newHead.y > mYTileCount - 2))
{//撞墙
setMode(LOSE);
return;
}
原来的版本是发现撞墙时就直接判定为失败,我这里做个小小的修改,让它可以穿墙而去:
private void updateSnake()
{
boolean growSnake = false;
// grab the snake by the head
Coordinate head = mSnakeTrail.get(0);
Coordinate newHead = new Coordinate(1, 1);
mDirection = mNextDirection;
switch (mDirection)
{
case EAST:
{
newHead = new Coordinate(head.x + 1, head.y);
break;
}
case WEST:
{
newHead = new Coordinate(head.x - 1, head.y);
break;
}
case NORTH:
{
newHead = new Coordinate(head.x, head.y - 1);
break;
}
case SOUTH:
{
newHead = new Coordinate(head.x, head.y + 1);
break;
}
}
//穿墙的处理
if (newHead.x == 0)
{//穿左边的墙
newHead.x = mXTileCount - 2;
}
else if (newHead.y == 0)
{//穿上面的墙
newHead.y = mYTileCount - 2;
}
else if (newHead.x == mXTileCount - 1)
{//穿右边的墙
newHead.x = 1;
}
else if (newHead.y == mYTileCount - 1)
{//穿下面的墙
newHead.y = 1;
}
// 判断是否撞到自己
int snakelength = mSnakeTrail.size();
for (int snakeindex = 0; snakeindex < snakelength; snakeindex++)
{
Coordinate c = mSnakeTrail.get(snakeindex);
if (c.equals(newHead))
{
setMode(LOSE);
return;
}
}
// 判断是否吃掉“苹果”
int applecount = mAppleList.size();
for (int appleindex = 0; appleindex < applecount; appleindex++)
{
Coordinate c = mAppleList.get(appleindex);
if (c.equals(newHead))
{
mAppleList.remove(c);
addRandomApple();
mScore++;
mMoveDelay *= 0.9;
growSnake = true;
}
}
// push a new head onto the ArrayList and pull off the tail
mSnakeTrail.add(0, newHead);
// except if we want the snake to grow
if (!growSnake)
{
mSnakeTrail.remove(mSnakeTrail.size() - 1);
}
int index = 0;
for (Coordinate c : mSnakeTrail)
{
if (index == 0)
{
setTile(YELLOW_STAR, c.x, c.y);
}
else
{
setTile(RED_STAR, c.x, c.y);
}
index++;
}
}
{
boolean growSnake = false;
// grab the snake by the head
Coordinate head = mSnakeTrail.get(0);
Coordinate newHead = new Coordinate(1, 1);
mDirection = mNextDirection;
switch (mDirection)
{
case EAST:
{
newHead = new Coordinate(head.x + 1, head.y);
break;
}
case WEST:
{
newHead = new Coordinate(head.x - 1, head.y);
break;
}
case NORTH:
{
newHead = new Coordinate(head.x, head.y - 1);
break;
}
case SOUTH:
{
newHead = new Coordinate(head.x, head.y + 1);
break;
}
}
//穿墙的处理
if (newHead.x == 0)
{//穿左边的墙
newHead.x = mXTileCount - 2;
}
else if (newHead.y == 0)
{//穿上面的墙
newHead.y = mYTileCount - 2;
}
else if (newHead.x == mXTileCount - 1)
{//穿右边的墙
newHead.x = 1;
}
else if (newHead.y == mYTileCount - 1)
{//穿下面的墙
newHead.y = 1;
}
// 判断是否撞到自己
int snakelength = mSnakeTrail.size();
for (int snakeindex = 0; snakeindex < snakelength; snakeindex++)
{
Coordinate c = mSnakeTrail.get(snakeindex);
if (c.equals(newHead))
{
setMode(LOSE);
return;
}
}
// 判断是否吃掉“苹果”
int applecount = mAppleList.size();
for (int appleindex = 0; appleindex < applecount; appleindex++)
{
Coordinate c = mAppleList.get(appleindex);
if (c.equals(newHead))
{
mAppleList.remove(c);
addRandomApple();
mScore++;
mMoveDelay *= 0.9;
growSnake = true;
}
}
// push a new head onto the ArrayList and pull off the tail
mSnakeTrail.add(0, newHead);
// except if we want the snake to grow
if (!growSnake)
{
mSnakeTrail.remove(mSnakeTrail.size() - 1);
}
int index = 0;
for (Coordinate c : mSnakeTrail)
{
if (index == 0)
{
setTile(YELLOW_STAR, c.x, c.y);
}
else
{
setTile(RED_STAR, c.x, c.y);
}
index++;
}
}
其实修改后的代码非常简单,就是把新节点的值做些处理,让它移动到对应的行/列的头部或尾部即可。下面就是修改后的“穿墙”贪食蛇的运行截图:
全屏机制
游戏一般都是全屏的,原始代码也考虑到标题栏太过难看了,于是使用下面这句代码就去掉了标题栏:
requestWindowFeature(Window.FEATURE_NO_TITLE);
可还是没有达到全屏的效果,在Android1.5中实现全屏效果非常简单,只需要一句代码即可实现:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
运行效果如下图所示:
声明:此博有部分内容为转载,版权归原作者所有~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗