基于JBox2D物理引擎开发的“雷电”小游戏(五)——碰撞

时间:2022-08-12 14:59:37

不好意思,隔了这么久才发这一篇文章,虽然部分原因是最近因为实习的事情很忙,还有一部分原因是比较懒,废话不多说,现在开始正文。

碰撞

既然学到了这里,想必大家都明白,物理引擎会帮我们做很多事情,省去从零开始码代码的工作量,当然“碰撞”也会由我们的物理引擎做好很多工作。

碰撞检测

什么是碰撞检测?碰撞检测就是当两个及两个以上的物体发生碰撞时,程序能够捕捉到是哪两个物体发生了碰撞。对,没错,我们就只需要设置一个监听器来帮助我们就好了。

public void initContactListener() { //加载碰撞监听器
ContactListener cl = new ContactListener() { //内部类
@Override
public void add(ContactPoint arg0) {//重写的方法
//碰撞后的行为
doAction(arg0.shape1.getBody(), arg0.shape2.getBody(), bl);
}

@Override
public void persist(ContactPoint arg0) {
} //重写persist方法

@Override
public void remove(ContactPoint arg0) {
} //重写remove方法

@Override
public void result(ContactResult arg0) {
}//重写result方法
};
world.setContactListener(cl);
}

我们用这个函数为游戏添加碰撞检测的监听器,每当有刚体发生碰撞时,ContactPoint类型的参数便能告诉程序是哪两个物体发生了碰撞,我们便可以为碰撞的刚体安排接下来的动作。

碰撞反应

检测到了是哪两个刚体后,我们便需要让刚体们在碰撞后“听我们的话”,让他们“按计划行事”。

public void doAction(Body body1, Body body2, ArrayList<MyBody> bl) {
//遍历刚体列表
for (MyBody mpi1 : bl) {
//匹配刚体
if (body1 == mpi1.body) {
//判断刚体类型
if (mpi1 instanceof MyRectColor) {
//类型强制转换
MyRectColor mrc = (MyRectColor) mpi1;
//判断是否为敌方“战机”
if (mrc.isObstacle) {
//遍历刚体列表
for(MyBody mpi2 : bl){
//匹配刚体
if(body2 == mpi2.body){
//具体的碰撞反应
obstacleAction(mpi1, mpi2);
}
}
}
} else if(mpi1 instanceof Bullet){
for(MyBody mpi2:bl){
if(body2 == mpi2.body) {
bulletAction(mpi1, mpi2);
}
}
} else if(mpi1 instanceof Prop){
for(MyBody mpi2:bl){
if(body2 == mpi2.body){
propAction(mpi1,mpi2);
}
}
}
}else if (body2 == mpi1.body) {
if (mpi1 instanceof MyRectColor) {
MyRectColor mrc = (MyRectColor) mpi1;
if (mrc.isObstacle) {
for(MyBody mpi2 : bl){
if(body1 == mpi2.body){
obstacleAction(mpi1, mpi2);
}
}
}
} else if(mpi1 instanceof Bullet){
for(MyBody mpi2:bl){
if(body1 == mpi2.body) {
bulletAction(mpi1, mpi2);
}
}
}else if(mpi1 instanceof Prop){
for(MyBody mpi2:bl){
if(body1 == mpi2.body){
propAction(mpi1,mpi2);
}
}
}
}
}
}

上面我给了部分的注释,其余没给注释的地方和上面类似,相信大家都看得懂。这部分代码只是简单将碰撞的刚体的类型分了个类,具体的碰撞反应在下面,不过在教学中,我就只给出obstacleAction(MyBody myBody1,MyBody myBody2)函数好了,其余的具体函数请看我的源码,这里就不粘上来了。

public void obstacleAction(MyBody myBody1,MyBody myBody2){
//强制类型转换
MyRectColor mrc = (MyRectColor) myBody1;
//判断刚体类型
if(myBody2 instanceof PlayerBall){
//玩家是否被保护
if(!isProtected) {
//强制类型转换
PlayerBall playerBall = (PlayerBall) myBody2;
playerBall.HP = playerBall.HP - mrc.obstacleAD;
if(playerBall.bulletPower>0) {
playerBall.bulletPower = playerBall.bulletPower - 25;
if(playerBall.bulletPower<0){
playerBall.bulletPower=0;
}
}else{
if(playerBall.bulletLevel>1){
playerBall.bulletLevel--;
playerBall.bulletPower=100;
}
}
if(playerBall.playerAD>playerBall.playerStartAD*0.6){
playerBall.playerAD = playerBall.playerAD*0.8;
if(playerBall.playerAD<playerBall.playerStartAD*0.6){
playerBall.playerAD=playerBall.playerStartAD*0.6;
}
}
isProtected = true;
//保护玩家1秒
new Thread(){
@Override
public void run(){
try{
sleep(1000);
}catch (Exception e){
}
isProtected = false;
}
}.start();
}
//判断是否是boss
if(mrc.level<bossLevel) {
//设置刚体isLive属性
mrc.isLive = false;
}
Message msg = new Message();
if(mrc.level==1) {
msg.what = 2;
handler.sendMessage(msg);
}else if(mrc.level==3){
msg.what = 3;
handler.sendMessage(msg);
}else if(mrc.level==6){
msg.what = 4;
handler.sendMessage(msg);
}
}else if(myBody2 instanceof MyRectColor){
MyRectColor myRectColor = (MyRectColor) myBody2;
if(myRectColor.isBottom){
mrc.isLive = false;
}else if(mrc.level==bossLevel&&myRectColor.isLeft){
mrc.isGoToRight = true;
}else if(mrc.level==bossLevel&&myRectColor.isRight){
mrc.isGoToRight = false;
}
}
}

当然啦,具体的动作自己定就好啦~相信大家也明白了物理引擎中的“碰撞”的机制,希望大家能够更加灵活的使用。