Если вы используете 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;
}
благодарит за ответ. Я был бы очень признателен, если бы вы объяснили, что происходит в методах 'gotFrame',' frameEventForFrameNumber' и 'frameEventForFrameNumber'. Также я хотел бы знать определение 'frameEventListenerWithContentsOfDictionary',' frameEventForListener' и 'FrameEvent'. – NSCodeman
FrameEvent - это класс, который я только что создал для своих целей, он предоставляет мне стандартный способ управления тем, что происходит в режиме «getFrame». Вы можете использовать любой простой объект NSDictionry, содержимое которого вы определяете для своих нужд. Я сделал это, потому что планирую иметь «фрейм» уведомления в нескольких контроллерах моего приложения, просто планируя здесь. – YvesLeBorg
Итак, главное - это метод 'attackActionFor'. – NSCodeman