免责声明:本系列教程是根据该系列教程实践过程所作的自己使用kobold2D框架经历。仅供学习与交流使用,请勿进行商业传播,转载时不要移除本声明。如果产生任何纠纷均与博客所有者无关。欢迎转载。
作者:Rush.xzj
上一篇文章我们已经把炮台,怪物,子弹都准备好了,现在我们需要做的是,当子弹碰到怪物的时候需要让怪物和子弹都消失。在这里就应用到碰撞检测,还好我们有CGRectIntersectsRect方法可以检测出2个矩形是否相交,也就是检测出碰撞
碰撞检测
消灭怪物就是要有没有任何一个子弹和怪物已经接触
为了实现上述的目的,我们需要对程序进行相应的更改。
保存当前屏幕上所有的子弹和怪物(在此我们用2个属性来实现)
打开HelloWorldLayer.h文件,添加如下的属性
NSMutableArray *monsters; NSMutableArray *projectiles;并添加如下的自定义常量:
#define kMonsterMark 1 #define kProjectileMark 2
在init方法中,初始化
//初始化怪物数组和子弹数组 monsters = [[NSMutableArray alloc] init]; projectiles = [[NSMutableArray alloc] init];
//设置tag以后会用到 monster.tag = kMonsterMark; [monsters addObject:monster];
-(void)finishShoot { [self addChild:projectile]; projectile.tag = kProjectileMark; [projectiles addObject:projectile]; projectile = nil; }
-(void)spriteMoveFinished:(id)sender{ CCSprite *sprite = (CCSprite *)sender; [self removeChild:sprite cleanup:YES]; if(sprite.tag == kMonsterMark) { [monsters removeObject:sprite]; } else if(sprite.tag == kProjectileMark) { [projectiles removeObject:sprite]; } }
这个时候添加一个碰撞检测代码:
//计算sprite所在的矩形区域 -(CGRect)calculateRectWithCCSprite:(CCSprite *)sprite { CGPoint point = sprite.position; CGSize size = sprite.contentSize; CGFloat startX = point.x - size.width / 2; CGFloat startY = point.y - size.height / 2; return CGRectMake(startX, startY, size.width, size.height); } -(void)update:(ccTime)dt { //需要删除的子弹 NSMutableArray *deleteProjectiles = [[NSMutableArray alloc] init]; for(CCSprite *selectProjectile in projectiles) { CGRect selectProjectileRect = [self calculateRectWithCCSprite:selectProjectile]; //是否已经打中 BOOL isHit = FALSE; //一个子弹一次子弹只能消灭一次怪物 CCSprite *deleteMonster = nil; for(CCSprite *selectMonster in monsters) { CGRect selectMonsterRect = [self calculateRectWithCCSprite:selectMonster]; //子弹与怪物是否已经接触了? if(CGRectIntersectsRect(selectMonsterRect, selectProjectileRect)) { isHit = TRUE; deleteMonster = selectMonster; //如果已经接触了,就跳出循环,直接进行下一个子弹的检测 break; } } if(isHit) { [self removeChild:deleteMonster cleanup:YES]; [monsters removeObject:deleteMonster]; [deleteProjectiles addObject:selectProjectile]; } } //把已经击中怪物的子弹移出去 for(CCSprite *deleteProjectile in deleteProjectiles) { [self removeChild:deleteProjectile cleanup:YES]; [projectiles removeObject:deleteProjectile]; } }
上面的代码应该非常清楚。我们仅仅通过遍历projectiles和targets数组,为每个projectile和target创建边界矩形,然后使用CGRectIntersectsRect来检测碰撞。如果发现有碰撞了,我们就从场景中移除精灵,同时也把它移除出数组。注意,我们不得不添加一个toDelete数组,因为我们不能在遍历一个数组的时候去删除数组中的对象。当然,还有许多方式可以实现类似的逻辑,我只不过挑选了简单的方法。
在你真正完成之前,还差最后一件事情。在你的init方法里面调用下面的函数:
//时刻查看是否有子弹和怪物碰撞 [self schedule:@selector(update:)];
怪物血量
在刚才运行的时候,是否已经发现了无论强的还是弱的怪物只需打一下怪物就消灭了,这个跟我们设计怪物的时候有点不一样。如果想让强怪物被打3下才消灭的话,这个时候就需要curHp这个属性值了,在update方法中if(isHit)修改成如下代码:
if(isHit) { Monster *hitMonster = (Monster *)deleteMonster; hitMonster.curHp--; [deleteProjectiles addObject:selectProjectile]; if(hitMonster.curHp <= 0) { [self removeChild:deleteMonster cleanup:YES]; [monsters removeObject:deleteMonster]; } }
到此为止,本篇教程就结束了。
该篇主要是介绍了消灭强弱怪物。敬请期待下一篇文章!