简体   繁体   中英

SKAction repeating each frame for count?

Does anyone know of a way in Sprite Kit to repeat an action each frame using a count? I was hoping the example below would work but all the repeats happen in the same update cycle.

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

OUTPUT:

[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:]

Alternatively I looked at (See below) but this is based on a duration not a specified number of calls, so it all depends on your framerate (which I don't believe you can access). If your running at 20FPS you get 10 "HELLO AGAIN!"s if your at 60FPS then you get 30.

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

EDIT:

It would seem that I was on the right track with SKAction repeatAction:count: , where I was going wrong was that NSLog(@"HELLO!"); (or any calculation you might do in the block) is an instantaneous action. If this is the case Sprite Kit repeats the action on the current frame only. The answer is to make the SKAction none instantaneous by adding a small delay via a sequence, now Sprite Kit executes the block once for each of the next 10 frames.

- (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];
}

OUTPUT:

[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:]

I think you can try the following:

@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
}

method of the SKScene object, which is called exactly once per frame as long as the scene is presented in a view and is not paused.

By default, this method does nothing. Your should override it in your scene subclass and perform any necessary updates to the scene.

SKScene Class Reference

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM