2013-07-09 4 views
2

Я хотел бы знать, когда определенные фреймы анимации запущены, чтобы установить различные условия. В приведенном ниже коде, как я могу использовать счетчик или задавать условия для определения, когда в настоящий момент работают определенные кадры анимации, скажем, 3-й и 8-й?Как определить, когда выполняются конкретные кадры анимации

NSMutableArray *frameArray = [NSMutableArray array]; 
for(int i = 1; i < 12; i++) 
{ 
    CCLOG(@"item %d added", i); 
    [frameArray addObject: 
    [birdSpriteFrameCache spriteFrameByName: 
     [NSString stringWithFormat:@"Sprite%d.png", i]]]; } 

//Starting the Animation 
CCAnimation *animation = [CCAnimation animationWithSpriteFrames:frameArray delay: 0.3]; 

id action =[CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation :animation]]; 
[firstSprite runAction:action]; 

ответ

2

Если вы используете cocos2d 2.0, в настоящее время подано уведомление на каждый фрейм. Прямо из документации:

/*******************/ 
/** Notifications **/ 
/*******************/ 
/** @def CCAnimationFrameDisplayedNotification 
    Notification name when a CCSpriteFrame is displayed 
*/ 
#define CCAnimationFrameDisplayedNotification @"CCAnimationFrameDisplayedNotification" 

При создании анимации, вы можете добавить к каждому кадру словарь USERINFO, который будет получен с уведомлением. Вот строка из CCActionInterval:

NSDictionary *dict = [frame userInfo]; 
if(dict) 
    [[NSNotificationCenter defaultCenter]  
      postNotificationName:CCAnimationFrameDisplayedNotification 
      object:target_ 
      userInfo:dict 
    ]; 

, так что я думаю, вы можете добавить объект Dict для рам 3 и 8 и «делать свое дело» в вызове уведомления обратно.

ob cit: не пробовал, но должен работать на вас.

EDIT: теперь попробовали. Мне потребовался всего один час, чтобы преобразовать очень неуклюжий алгоритм, основанный на времени, в надежную реализацию, управляемую событиями, в одном из классов боевого контроля. Я получаю уведомление только для 2 кадров: 9-й кадр анимации атаки (где я могу теперь в идеальной синхронизации воспроизвести звук оружия) и 11-й кадр поврежденной анимации (где, если жертва умирает, я могу просто остановиться анимация и медленно исчезает криттер). Путь к команде cocos2d. Не все так сложно, API чистый и четкий.

Вот часть кода (моя первая трещина на нем, а не гордость :)), код использует некоторые из моих других вещей, но вы должны быть в состоянии начать работу с общей идеей.

-(void) registerForFrames{ 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(gotFrame:) 
               name:CCAnimationFrameDisplayedNotification 
               object:nil]; 
} 

-(void) deregisterForFrames { 

    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:CCAnimationFrameDisplayedNotification 
                object:nil]; 

} 

-(NSDictionary *) frameEventForFrameNumber:(NSUInteger) frameNumber 
           animation:(NSString *) animationType { 

    return [[FrameEvent frameEventForListener:frameListenerCombatController 
           animationName:animationType 
            frameNumber:frameNumber] asDictionary]; 

} 

-(FrameEvent*) frameEventForFrame:(NSDictionary *) theDic{ 
    return [FrameEvent frameEventListenerWithContentsOfDictionary:theDic]; 
} 

-(void) gotFrame:(id) notification{ 

    NSDictionary *userInfoDictionary = [notification userInfo]; 
    FrameEvent *ev = [self frameEventForFrame:userInfoDictionary]; 
    if (!ev) { 
     MPLOGERROR(@"*** userInfo returned nil frameEvent object, bailing out!"); 
     return; 
    } 

    if (ev.frameListenerType==frameListenerUnknown){ 
     MPLOGERROR(@"*** Got served an unknown dictionary, bailing out!"); 
     return; 
    } 

    if (ev.frameListenerType==frameListenerCombatController) { 

     MPLOG(@"Got Frame %@",ev.description); 

     if([ev.animationName isEqualToString:@"attack"]) { 
      [self scheduleOnce:@selector(attackTurnAround) delay:0.]; 
     } 

     if ([ev.animationName isEqualToString:@"hurt"]) { 
      // more here ! 
      MPLOG(@"TODO : schedule dead critter method"); 
     } 
    } else { 
     MPLOGERROR(@"*** Not processing frame listener of type [%@], bailing out!", 
     [GEEngineSpecs frameListenerAsString:ev.frameListenerType]); 
    } 
} 

и, наконец, ключевая часть, поместить информацию о пользователе на раме:

- (CCAction *)attackActionFor:(GEClassAnimationSpec *)animSpec playerAsString:(NSString *)playerKey { 

    NSMutableArray *animFrames = [NSMutableArray array]; 
    for (int i = 1; i <= animSpec.frames; i++) { 
     NSString  *sfn = [NSString stringWithFormat:@"%@%@%i.png", animSpec.fileName, playerKey, i]; 
     CCSpriteFrame *sf = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:sfn]; 
     [animFrames addObject:sf]; 

    } 

    float animFrameDelay = 1.0f/K_ATTACK_FRAME_RATE; 
    CCAnimation *anim = [CCAnimation animationWithSpriteFrames:animFrames delay:animFrameDelay]; 
    anim.restoreOriginalFrame = NO; 

    CCAnimationFrame * ninth = [anim.frames objectAtIndex:8]; 
    NSDictionary *ui = [self frameEventForFrameNumber:9 animation:@"attack"]; 
    ninth.userInfo=ui; 

    CCAction *action = [CCSequence actions: 
     [CCAnimate actionWithAnimation:anim], 
     [CCCallFunc actionWithTarget:self selector:@selector(resumeAttackerIdle)], 
     nil 
    ]; 
    return action; 
} 
+0

благодарит за ответ. Я был бы очень признателен, если бы вы объяснили, что происходит в методах 'gotFrame',' frameEventForFrameNumber' и 'frameEventForFrameNumber'. Также я хотел бы знать определение 'frameEventListenerWithContentsOfDictionary',' frameEventForListener' и 'FrameEvent'. – NSCodeman

+0

FrameEvent - это класс, который я только что создал для своих целей, он предоставляет мне стандартный способ управления тем, что происходит в режиме «getFrame». Вы можете использовать любой простой объект NSDictionry, содержимое которого вы определяете для своих нужд. Я сделал это, потому что планирую иметь «фрейм» уведомления в нескольких контроллерах моего приложения, просто планируя здесь. – YvesLeBorg

+0

Итак, главное - это метод 'attackActionFor'. – NSCodeman

0

Это в уведомлениях как кто-то другой упоминалось, но, как ХА: У меня были некоторые проблемы с этим а в то время как у меня было два разных спрайта, которые запускали одну и ту же анимацию, начиная с немного разных времен.

Я думаю это было запуская уведомление каждый раз, как спрайт хит этот кадр, и я в конечном итоге слом, что кусок кода, потому что я не мог понять, как координата, спрайт был запуск, и завелся с потому что я не мог заставить его себя вести.

Просто что-то, чтобы посмотреть, если вы получаете дурацкие результаты.

+5

Это должно быть комментарий к другому ответу, а не ответ на его собственный. Было бы намного выгоднее, если бы вы упомянули о своем другом подходе в качестве ответа. – oopology

+0

@redux: см. Код ниже, я получил это, чтобы «вести себя» на моем первом модульном тесте. – YvesLeBorg

Смежные вопросы