如何使用kobold2d来做一个简单的iphone游戏教程(第五部分)

免责声明:本系列教程是根据该系列教程实践过程所作的自己使用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];

当一个怪物从右侧出现的时候需要把这个怪物添加到monsters中,在addMonster方法中最后添加:

    //设置tag以后会用到
    monster.tag = kMonsterMark;
    [monsters addObject:monster];

发射子弹的时候,也需要把子弹添加到projectiles,修改finishShoot方法如下所示:

-(void)finishShoot {
    [self addChild:projectile];
    projectile.tag = kProjectileMark;
    [projectiles addObject:projectile];
    
    projectile = nil;
}

当子弹或者怪物离开屏幕的时候,在清理spriteMoveFinished方法中:

-(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];
            }
        }

这个时候再次运行就可以看到,当强的怪物被击中三次才会消失

到此为止,本篇教程就结束了。

该篇主要是介绍了消灭强弱怪物。敬请期待下一篇文章!


你可能感兴趣的:(游戏,框架,iPhone)