2.4 碰撞检测
很快大家就会发现,射出的子弹和敌机都是“擦肩而过”,毫无威力,这显然不合逻辑。这里我们介绍Cocos2D里常用的碰撞检测方法,用于检测游戏对象之间的碰撞。虽然这种碰撞比较简单,检测精度也不是很高,但是对于一般游戏来说已经足够了。
在介绍实际的碰撞检测方法之前,我们需要一个辅助方法,根据精灵当前的位置算出它的“可碰撞区域”,如代码清单2-24所示。
代码清单2-24 辅助方法的实现
-(CGRect) rectOfSprite:(CCSprite*)sprite{
returnCGRectMake(sprite.position.x - sprite.contentSize.width / 2,
sprite.position.y - sprite.contentSize.height /2,
sprite.contentSize.width, sprite.contentSize.height);
}
此方法根据精灵所在位置和精灵的实际大小计算出一个矩形区域代表精灵的可碰撞区域。
具体的碰撞检测代码如代码清单2-25所示。
代码清单2-25 碰撞检测
-(void) collisionDetection:(ccTime)dt{
CCSprite *enemy;
CGRectbulletRect = [self rectOfSprite:_bulletSprite];
CCARRAY_FOREACH(_enemySprites, enemy)
{
if (enemy.visible) {
//1.bullet & enemy collision detection
CGRectenemyRect = [self rectOfSprite:enemy];
if (_bulletSprite.visible&&CGRectIntersectsRect(enemyRect, bulletRect)) {
enemy.visible = NO;
_bulletSprite.visible = NO;
[_bulletSpritestopAllActions];
[enemystopAllActions];
CCLOG(@"collision bullet");
break;
}
//2.enemy & player collision detection
CCSprite *playerSprite = (CCSprite*)[self getChildByTag:kTagPalyer];
CGRectplayRect = [self rectOfSprite:playerSprite];
if (playerSprite.visible&&
playerSprite.numberOfRunningActions == 0
&&CGRectIntersectsRect(enemyRect, playRect)) {
enemy.visible = NO;
id blink = [CCBlink actionWithDuration:2.0 blinks:4];
[playerSpritestopAllActions];
[playerSpriterunAction:blink];
CCLOG(@"collision player");
break;
}
}
}
}
在这个游戏中我们只需要关心子弹与敌机的碰撞、敌机与玩家飞机的碰撞就行了。因此,首先我们计算出子弹的碰撞区域,遍历所有的敌机,逐个判断敌机与子弹以及敌机与玩家飞机之间的碰撞。
注意 这里用CGRectIntersectsRect方法检测碰撞,此方法判断两个矩形是否相交。如果形状不规则,或者原始精灵图片的透明像素过多,这种检测方法就会非常不准确。后面学习物理引擎时,我们将介绍一种更加精确的碰撞检测方法。
这里需要注意两点:
检测对象必须在屏幕可见范围之内;
检测到碰撞以后需要停止action,再做相应的碰撞处理逻辑,比如让敌机消失、计分之类。
当然,由于此处敌机采用复用的方式,击中以后并不是删除这个对象,而只是把可见性设置为NO,然后放回数组里,下次又可从里面再取出来,再次向玩家发起进攻。
编译并运行,体验杀死敌机的快感吧!