SKAction повторяет каждый кадр для подсчета?

Кто-нибудь знает способ в Sprite Kit повторять действие в каждом кадре, используя счетчик? Я надеялся, что приведенный ниже пример сработает, но все повторения происходят в одном и том же цикле обновления.

SKAction *helloAction = [SKAction runBlock:^{
    NSLog(@"HELLO!");
}];
SKAction *repeatBlock = [SKAction repeatAction:helloAction count:10];
[self runAction:repeatBlock];

ВЫВОД:

[14972:70b] -[MyScene update:]
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] HELLO!
[14972:70b] -[MyScene update:]
[14972:70b] -[MyScene update:]
[14972:70b] -[MyScene update:]
[14972:70b] -[MyScene update:]

В качестве альтернативы я посмотрел (см. ниже), но это основано на продолжительности, а не на указанном количестве вызовов, поэтому все зависит от вашей частоты кадров (к которой я не верю, что вы можете получить доступ). Если вы работаете со скоростью 20 кадров в секунду, вы получите 10 «HELLO AGAIN!», если со скоростью 60 кадров в секунду, вы получите 30.

SKAction *helloAction = [SKAction customActionWithDuration:0.5 actionBlock:^(SKNode *node, CGFloat elapsedTime) {
    NSLog(@"HELLO AGAIN!");
}];
[self runAction:helloAction];

РЕДАКТИРОВАТЬ:

Казалось бы, что я был на правильном пути с SKAction repeatAction:count:, где я ошибся, так как NSLog(@"HELLO!"); (или любое вычисление, которое вы могли бы сделать в блоке) является мгновенным действием. В этом случае Sprite Kit повторяет действие только для текущего кадра. Ответ заключается в том, чтобы сделать SKAction не мгновенным, добавив небольшую задержку через последовательность, теперь Sprite Kit выполняет блок один раз для каждого из следующих 10 кадров.

- (void)testMethod {
    SKAction *myAction = [SKAction runBlock:^{
        NSLog(@"BLOCK ...");
    }];
    SKAction *smallDelay = [SKAction waitForDuration:0.001];
    SKAction *sequence = [SKAction sequence:@[myAction, smallDelay]];
    SKAction *repeatSequence = [SKAction repeatAction:sequence count:10];
    [self runAction:repeatSequence];
}

ВЫВОД:

[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]
[399:60b] BLOCK ...
[399:60b] -[MyScene update:]

person fuzzygoat    schedule 21.01.2014    source источник
comment
это решение больше не работает с iOS 9.   -  person Alon Genosar    schedule 06.11.2015
comment
для iOS 9 я установил задержку на 1/60.0   -  person Alon Genosar    schedule 05.02.2016
comment
обратите внимание, что вы можете тривиально использовать функцию Update() в сцене, если это поможет. По-идиотски Apple забыла функцию обновления в спрайтах.   -  person Fattie    schedule 28.11.2017


Ответы (1)


Я думаю, вы можете попробовать следующее:

@property (nonatomic) NSInteger frameCounter;

- (void)didEvaluateActions
{
     if (self.frameCounter < 10){
          [self runAction:(SKAction *) yourAction];
          self.frameCounter++;
     }
     // frameCounter to be set to 0 when we want to restart the update for 10 frames again
}

метод объекта SKScene, который вызывается ровно один раз за кадр, пока сцена представлена ​​в представлении и не приостановлена.

По умолчанию этот метод ничего не делает. Вы должны переопределить его в своем подклассе сцены и выполнить все необходимые обновления сцены.

Справочник по классу SKScene

person tanzolone    schedule 21.01.2014
comment
Спасибо за ответ, но я хочу, чтобы действие вызывалось только один раз для каждого из следующих 10 кадров. То, что у вас есть, будет вызываться один раз за кадр навсегда. - person fuzzygoat; 21.01.2014
comment
Извините, я пропустил, что вам нужно это каждые 10 кадров! Я обновил ответ - я предполагаю, что вы все еще можете использовать этот метод (поскольку он позволяет вам подсчитывать точное количество кадров), и вы можете использовать счетчик для выполнения действия только каждые 10 кадров. Может ли это работать? - person tanzolone; 21.01.2014
comment
Действие runBlock здесь излишне. Это если код счетчика кадров уже запускает каждый кадр для следующих 10 кадров. Теперь вам нужно только написать код непосредственно в этом методе или отправить сообщение другому объекту для выполнения задачи. - person LearnCocos2D; 21.01.2014
comment
Я обновил ответ: определенно вам просто нужно выполнить в операторе if любые действия, которые вам нужны. - person tanzolone; 21.01.2014
comment
Спасибо за подсказки, ребята, я отредактировал свой вопрос, чтобы показать свои выводы ... Очень признателен. - person fuzzygoat; 22.01.2014