实现分析 - Enemy part2

-(void)changeState:(CharacterStates)newState {
if (characterState == kStateDead)
return; // No need to change state further once I am dead

[self stopAllActions];
id action = nil;
characterState = newState;
switch (newState) {
     case kStateSpawning:
          [self runAction:[CCFadeOut actionWithDuration:0.0f]];  // Fades out the sprite if it was visible before
          [self setDisplayFrame:  [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"teleport.png"]];
          action =  [CCSpawn actions:
                     [CCRotateBy actionWithDuration:1.5f angle:360],
                     [CCFadeIn actionWithDuration:1.5f], nil];
          break;

     case kStateIdle:
          CCLOG(@"EnemyRobot->Changing State to Idle");
          [self setDisplayFrame: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"an1_anim1.png"]];
           break;

     case kStateWalking:
           CCLOG(@"EnemyRobot->Changing State to Walking");
           if (isVikingWithinBoundingBox)
           break; // AI will change to Attacking on next frame
           
     float xPositionOffSet = 150.0f;
     if (isVikingWithinSight) {
     if ([vikingCharacter position].x < [self position].x) xPositionOffSet = xPositionOffSet * -1;
     // Invert to -150
     } else {
          if (CCRANDOM_0_1() > 0.5f) xPositionOffSet = xPositionOffSet * -1;
          if (xPositionOffSet > 0.0f) {
               [self setFlipX:YES];
           } else {
               [self setFlipX:NO];
           }
     }
      action = [CCSpawn actions: 
                 [CCAnimate actionWithAnimation:robotWalkingAnim restoreOriginalFrame:NO],
                 [CCMoveTo actionWithDuration:2.4f position:ccp([self position].x + xPositionOffSet,[self position].y)], nil];
           break;

      case kStateAttacking:
           CCLOG(@"EnemyRobot->Changing State to Attacking");
           action = [CCSequence actions:
                     [CCAnimate actionWithAnimation:raisePhaserAnim restoreOriginalFrame:NO],
                     [CCDelayTime actionWithDuration:1.0f],
                     [CCAnimate actionWithAnimation:shootPhaserAnim restoreOriginalFrame:NO],
                     [CCCallFunc actionWithTarget:self selector:@selector(shootPhaser)],
                     [CCAnimate actionWithAnimation:lowerPhaserAnim restoreOriginalFrame:NO],
                     [CCDelayTime actionWithDuration:2.0f], nil];
            break;

            case kStateTakingDamage:
            CCLOG(@"EnemyRobot->Changing State to TakingDamage");
            if ([vikingCharacter getWeaponDamage] > kVikingFistDamage){
                 // If the viking has the mallet, then 
                action = [CCAnimate actionWithAnimation:headHitAnim restoreOriginalFrame:YES];
            } else {
                  // Viking does not have weapon, body blow
                action = [CCAnimate actionWithAnimation:torsoHitAnim restoreOriginalFrame:YES];
            }
            break;

      case kStateDead:
                              CCLOG(@"EnemyRobot -> Going to Dead State");
            action = [CCSequence actions: [CCAnimate actionWithAnimation:robotDeathAnim restoreOriginalFrame:NO],
                      [CCDelayTime actionWithDuration:2.0f],
                      [CCFadeOut actionWithDuration:2.0f],
             nil];
             break;

             default: CCLOG(@"Enemy Robot -> Unknown CharState %d",characterState);
             break;
    }

if (action != nil)
        [self runAction:action];
}

 


死亡:


(AI)gameUpdate 会在“适当的时候“来调用changeState,所以gameUpdate的责任是思考----” 如果是什么什么情况,就怎么样“。。。 如此这般。

然后决定了要”怎么样“,由改变状态 changeState来处理。 (just like your boss & you)

每次状态的改变应该带来行为的改变,例如本来在巡逻”walking“的敌人,在发现玩家后会改为”攻击“状态。所以stopAllAction在开始便要执行。


----  下面是AI部分

-(void)updateStateWithDeltaTime:(ccTime)deltaTime andListOfGameObjects:(CCArray*)listOfGameObjects {
    [self checkAndClampSpritePosition];
    if ((characterState != kStateDead) && (characterHealth <= 0)) {
        [self changeState:kStateDead];
        return;
    }
    vikingCharacter = (GameCharacter*)[[self parent] getChildByTag:kVikingSpriteTagValue];
    CGRect vikingBoundingBox = [vikingCharacter adjustedBoundingBox];
    CGRect robotBoundingBox = [self adjustedBoundingBox];
    CGRect robotSightBoundingBox = [self eyesightBoundingBox];
    isVikingWithinBoundingBox = CGRectIntersectsRect(vikingBoundingBox, robotBoundingBox) ? YES : NO;
    isVikingWithinSight = CGRectIntersectsRect(vikingBoundingBox, robotSightBoundingBox)? YES : NO;

    if ((isVikingWithinBoundingBox) && ([vikingCharacter characterState] == kStateAttacking)) {
     // Viking is attacking this robot
    if ((characterState != kStateTakingDamage) && (characterState != kStateDead)) {
        [self setCharacterHealth: [self characterHealth] – [vikingCharacter getWeaponDamage]];
       if (characterHealth > 0) {
            [self changeState:kStateTakingDamage];
        } else {
            [self changeState:kStateDead];
        }
       
       return; // Nothing to update further, stop and show damage
    }
    } 

if ([self numberOfRunningActions] == 0) {   // -- 1
    if (characterState == kStateDead) {
        // Robot is dead, remove
        [self setVisible:NO];
        [self removeFromParentAndCleanup:YES];
     } else if ([vikingCharacter characterState] == kStateDead) {
         // Viking is dead, walk around the scene
         [self changeState:kStateWalking];
     } else if (isVikingWithinSight) {
         [self changeState:kStateAttacking];
     } else {
          // Viking alive and out of sight, resume walking
          [self changeState:kStateWalking];
     }
  } 
}



1-- 关键的一句

例如创建时状态是spawning,此时 updateStateWithDeltaTime 判断为:执行一个1.5s 的动画action。

如果没有1,enemy的状态会在下一个运算循环中被改为其它状态。

numberOfRunningActions 让enemy在做完前一阶段的动作后,再回到AI判断,下一阶段应该是什么。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值