2013-04-20 4 views
1

Каждый сейчас, а затем добавить некоторые пульсирующие спрайтов к моей сцене так:Syncing спрайтов анимации в cocos2d

CCSpriteBatchNode *batch = (CCSpriteBatchNode*) [scene getChildByTag: foo1]; 

sprite = [CCSprite spriteWithBatchNode:batch rect:CGRectMake(0, 0, 128, 128)]; 
sprite.position = foo2 
CCTintTo *a = [CCTintTo actionWithDuration: .5 red:128 green: 128 blue: 128]; 
CCTintTo *b = [CCTintTo actionWithDuration: .5 red:255 green: 255 blue: 255]; 

[sprite runAction:[CCRepeatForever actionWithAction: 
        [CCSequence actionOne: a two: b]]]; 

[batch addChild: sprite]; 

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

ответ

2

hmmm ... не легкий. Единственный способ, которым я буду видеть, что делать это, чтобы запланировать «» flasherRamp так:

в .h

NSMutableArray *flashers; 

в ом, методе инициализации

flashers = [[NSMutableArray array] retain]; // choose your own ARC flavor, if you retain 
              // dont forget to release in dealloc 

[self schedule:@selector(flasherRamp) interval:1.0f]; 

в ом , где вы создаете спрайт

foo2.visible=NO; 
[flashers addObject foo2]; 

наконец

-(void) flasherRamp { 
    for (CCSprite *flasher in flashers) { 
     CCTintTo *a = [CCTintTo actionWithDuration: .5 red:128 green: 128 blue: 128]; 
     CCTintTo *b = [CCTintTo actionWithDuration: .5 red:255 green: 255 blue: 255]; 

     [flasher runAction:[CCRepeatForever actionWithAction: 
       [CCSequence actionOne: a two: b]]]; 
     flasher.visible=YES; 
    } 
    [flashers removeAllObjects]; 
} 

пс. в конце концов, может быть некоторый дрейф, в зависимости от того, как долго это продолжается.

pps. с точки зрения удобства использования, это не может быть хорошей идеей, если есть какая-то причинность между появлением мигающих спрайтов и некоторым «асинхронным» игровым событием, которое может вызвать задержку до 1 секунды между инициирующим событием и фактическим появлением мигалки.

ob cit. : закодировано из памяти, не проверено, но должно быть близко.

+0

Спасибо за предложение. Для моего случая я должен иметь возможность добавлять мигалки в произвольные моменты времени (игрок создает их). Я посмотрю на более низкоуровневые способы анимации ... – borkbork

+0

Тогда я бы держался подальше от действия CCTintTo и реализовал это аналогично при обновлении, таком как запланированный метод, с массивом объектов flasher и обновил цвет каждого объекта в массиве в каждом цикле. , Все еще сложный код. g'luck. – YvesLeBorg

0

В этом случае я бы не стал использовать CCRepeatForever.

Создайте перечисление, определяющее текущее состояние оттенка (tintGray, tintWhite, tintDone), затем создайте селектор по расписанию, который проверяет состояние.

Как только состояние будет завершено, повторите действия, но для каждого ребенка batchnode (при условии, что это единственные дети).

Чтобы запланировать селектор, поместите его в вашем инициализации или другой метод загрузки:

// be sure to schedule the interval at a fast enough rate 
[self schedule:@selector(tick:) interval:0.1f]; 

Затем определим метод следующим образом:

-(void)tick:(ccTime)dt 
{ 
    if(tintState == tintDone) 
    { 
     [self unschedule:@selector(tick:)]; 
     [self tinter]; 
    } 
} 

Затем планировать действия оттенка для всех спрайтов :

-(void)tinter 
{ 
    // could init and reuse this somewhere else to save on allocs 
    CCSequence *actions = [CCSequence actions: 
         [CCCallBlockN actionWithBlock:^(CCNode* node) 
         { 
          tintState = tintGray; 
         }], 
         [CCTintTo actionWithDuration: .5 red:128 green: 128 blue: 128], 
         [CCCallBlockN actionWithBlock:^(CCNode* node) 
         { 
          tintState = tintWhite; 
         }], 
         [CCTintTo actionWithDuration: .5 red:255 green: 255 blue: 255], 
         [CCCallBlockN actionWithBlock:^(CCNode* node) 
         { 
          tintState = tintDone; 
         }], 
         nil]; 

    CCSpriteBatchNode *batch = (CCSpriteBatchNode*) [scene getChildByTag: foo1]; 
    for (CCSprite *flasher in batch.children) 
    { 
     [flasher stopAllActions]; 
     [flasher runAction:actions]; 
    } 

    // reschedule tick checking 
    [self schedule:@selector(tick:) interval:0.1f]; 
} 

Очевидно, что это не идеально, поскольку флаг будет управляться первый спрайт для завершения тонирования, но задержка должна быть незначительной. Если вы хотите убедиться, что все они закончили, просто измените флаг на число запусков числа спрайтов, так что «tinter» только вызывается, как только tintState равен количеству спрайтов в batchnode.

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