Как анимировать несколько SKSpriteNode вместе?

Я довольно новичок в SpriteKit, У меня есть набор узлов, которые необходимо переместить вместе в разные точки для каждого узла, и после завершения анимации для всех них я хотел бы сделать что-то еще.

Я делал это с UIView компоненты до. [UIView animateWithDuration:completion:] Блок давал то, что мне было нужно. Но в SpriteKit каждый узел имеет свое собственное действие и анимирует сам по себе. Я не смог найти блок анимации для узлов спрайта. Поэтому я не могу контролировать завершение анимации.

Надеюсь, мне понятно. Заранее спасибо.

1 ответ

Есть пара методов класса SKAction, которые могут представлять интерес. Первый - runBlock: и второй - группа: (это позволяет параллельно выполнять действия).

Вы можете запускать действия на узлах с обработчиком завершения, используя runAction: complete:

Следующий код помещает каждое "действие анимации" вместе с блоком завершения в "действие блока". Затем действия блока помещаются в "групповое действие". Наконец, групповое действие приказано запустить. Это приводит к тому, что каждое действие блока запускается одновременно. Обработчик завершения каждого действия блока вызывает метод с именем checkCompletion. Этот метод проверяет наличие узлов (с определенным значением свойства name), которые по- прежнему анимируются, вызывая hasActions для узла. Поскольку узел, вызвавший метод checkCompletion, вернет YES, если только один узел вернет YES, то все анимации выполнены.

Следующий пример демонстрирует это с использованием двух узлов, однако он будет работать более двух.

// assuming two SKNode subclasses named 'node1' and 'node2' AND 'self' is an SKScene subclass


// assign each animating node the same name (used in checkCompletion method)
node1.name = @"animating";
node2.name = @"animating";
// in this example both nodes will animate to the origin
CGPoint origin = CGPointMake(0.0, 0.0);
// make move actions for nodes
SKAction *shortMove = [SKAction moveTo:origin duration:1.2];
SKAction *longMove = [SKAction moveTo:origin duration:4.8];
// wrap nodes in their own separate block action
SKAction *moveNode1 = [SKAction runBlock:^{
    [node1 runAction:shortMove completion:^{
        NSLog(@"shortMove complete");
        [self checkCompletion];
    }];
}];
SKAction *moveNode2 = [SKAction runBlock:^{
    [node2 runAction:longMove completion:^{
        NSLog(@"longMove complete");
        [self checkCompletion];
    }];
}];
// put block actions in a group action
SKAction *groupAction = [SKAction group:@[moveNode1, moveNode2]];
// execute group action
[self runAction:groupAction];

метод checkCompletion -

- (void)checkCompletion {

     __block int currentlyHasActions = 0;
     // check for all actions complete on animating nodes
     [self enumerateChildNodesWithName:@"animating" usingBlock:^(SKNode *node, BOOL *stop){
         if ([node hasActions]) {
             currentlyHasActions++;
             // prevent unnecessary enumeration
             if (currentlyHasActions > 1) { *stop = YES; }
         }
     }];
     if (currentlyHasActions == 1) {
         NSLog(@"Actions Finished!!!");

         // execute completion code here...

     }
}

К сожалению, следующее не будет работать, так как длительность действия блока является мгновенной. Следовательно, продолжительность группового действия в этом случае также является мгновенной. Это причина для метода checkCompletion.

[self runAction:groupAction completion:^{
     // completion code here... :(
}];
Другие вопросы по тегам