Как анимировать несколько 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... :(
}];