<a href="http://www.jianshu.com/p/55d93ffc7138">上一篇</a>实现了主角打中敌机,敌机死亡并且显示爆炸效果,今天这里主要来实现主角被敌机碰撞以及被敌机子弹打中的效果和逻辑处理。

1.打开主角类DrawPlayer
- 先给主角定义一个血量值
/**
* 主角血量
*/
private float mLife =20;
- 主角被敌机击中以后在一定时间内处于无敌状态,不再受任何伤害。
/**
* 是否被击中,被击中后闪烁 并且一定时间内无敌。
*/
private boolean isCollision=true;
private int noCollisionCount;```
- 新增两个方法处理主角和敌机的碰撞以及和敌机子弹的碰撞
/**
* 和敌机碰撞
* @param en
* @return
*/
public boolean isCollisionWith(DrawEnemy en){
if(!isCollision){
//获取到敌机的xy坐标
float ex = en.getEnemyX();
float ey = en.getEnemyY();
int ew = en.getWidth()/2;
int eh = en.getHeight()/2;
//得到主角当前位置,主角的高宽和敌机的坐标位置进行对比,如果坐标范围出现重叠 说明敌机和主角碰撞了。
if(getPlayerX()+getWidth()/2<=ex||getPlayerX()-getWidth()/2>=ex+ew){
return false;
}
if(getPlayerY()>=ey+eh||getPlayerY()+getHeight()<=ey){
return false;
}
isCollision=true;
return true;
}else{
return false;
}
}```
/**
* 和敌机子弹碰撞
* @param bullet
* @return
*/
public boolean isCollisionWith(DrawEnemyBullet bullet){
if(!isCollision){
//获取敌机子弹的xy坐标
float bx = bullet.getBulletX();
float by = bullet.getBulletY();
float bw = bullet.getWidth();
float bh=bullet.getHeight();
//计算逻辑和上面主角敌机碰撞一样,每一颗子弹也是一个对象。
if(getPlayerX()+getWidth()/2<=bx||getPlayerX()>=bx+bw){
return false;
}
if(getPlayerY()>=by+bh||getPlayerY()+getHeight()/2<=by){
return false;
}
isCollision=true;
return true;
}else{
return false;
}
}```
这里的实现逻辑和上一篇的碰撞逻辑一样,通过获取敌机每一颗子弹或者敌机的xy坐标以及主角的xy坐标判断是否出现范围重叠,如果重叠说明发生碰撞。
- 绘制主角的血槽在最顶部位置。
int screenW = ScreenUtils.getScreenWidth(getContext());
mPaint.setColor(Color.WHITE);
int lifeH = SizeUtils.dp2px(getContext(),20);
mPaint.setStrokeWidth(SizeUtils.dp2px(getContext(),3));
canvas.drawLine(screenW/6, lifeH,screenW/5+ mLife *50,lifeH,mPaint);```
- 最后在updateGame方法中处理无敌状态的刷新
@Override
void updateGame() {
if(isCollision){
noCollisionCount++;
if(noCollisionCount>=60){
isCollision=false;
noCollisionCount=0;
}
}
}```
上面就是在主角类新增的内容,内容不多,主要新增一个血槽和被敌机击中以及无敌状态的处理。
######2.回到GameView类调用上面的方法。
- 在<b>onDrawEnemy</b>方法中循环绘制敌机的时候调用主角类的<b>isCollisionWith(DrawEnemy en)</b>方法判断是否发生碰撞,主要判断的是敌机和主角的碰撞。

如果发生碰撞,主角掉三滴血,敌机死亡并且添加死亡爆炸效果。
- 在<b>dieEnemyBullet</b>方法中循环绘制敌机子弹的时候调用主角类的<b>isCollisionWith(DrawEnemyBullet bullet)</b>方法判断是否发生碰撞,主要是判断敌机子弹和主角的碰撞。

主角和敌机子弹碰撞,敌机该子弹失效,主角掉一滴血。
- 新增一个游戏状态
private final static int OVER=3;//主角死亡 游戏结束
- 在<b>onGameDraw</b>中需要每次都去判断主角的血量,如果<=0说明主角已经死亡,游戏结束。

- 游戏结束后弹出提示框,因为绘制过程是在非主线程中完成的,但是弹出提示框需要通过主UI完成,所以我这里采用<a href="https://developer.android.google.cn/reference/android/os/Handler.html">Handler</a>显示提示框。
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(mDialog==null){
mDialog = new AlertDialog.Builder(getContext());
mDialog.setMessage("战机被摧毁,游戏结束");
mDialog.setTitle("提示");
mDialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
((Activity)getContext()).finish();
}
});
mDialog.setCancelable(true);
mDialog.show();
}
}
};```
<b>GameView</b>中新增内容不多,主要在之前已经实现的方法中新增一些逻辑处理来完善游戏思路。
Canvas学习过程差不多就快结束了,下一篇就是游戏中的大BOSS了。
<a href="https://github.com/tangyxgit/GameCanvas">源码</a>已经通过Git更新。
<a href="http://www.jianshu.com/p/55d93ffc7138">上一篇</a>
网友评论