简体   繁体   中英

Wait after [SKAction playSoundFileNamed:waitForCompletion:]

Alright, this one makes me feel like a complete idiot.

I have a method in my game that's meant to animate the text in a text box by making it pop up one letter at a time. In my DDTextBox class, there's a method that animates it called animateText . Here's the coding of it:

for (NSUInteger i = 1; i <= _text.length; i++)
    {
        [_scene runAction:[SKAction playSoundFileNamed:@"regularTextBeep.m4a" waitForCompletion:YES] completion:^{
            [_scene runAction:[SKAction waitForDuration:0.2] completion:^{
                ((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).text = (NSString*)[_text substringToIndex:i];

                ((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).position = CGPointMake(20 + (((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).frame.size.width / 2.0), ((SKLabelNode*)[_scene childNodeWithName:@"insideOfTextBox"]).frame.size.height - (((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).frame.size.height / 2.0) - 15);
                NSLog(@"Textbox loading a letter on iteration %u", i);
            }];
        }];
    }
    completion();

It's meant to make the node named textBoxText change so it's the substring of the string _text up to an index i , then wait until the sound file is over until it moves on to the next character.

Currently, the sound plays once, and all of the text pops up at the same time. The audio file in question is about 200 ms long. How would I make it so it plays the same file over and over again? Would I declare the SKAction outside of the method call for [self runAction:completion:] ? Any ideas?

You can do so by creating a sequence of actions. You might need to make some adjustments.

NSMutableArray *marrActions = [NSMutableArray new];

for (NSUInteger i = 1; i <= _text.length; i++)
{

    [marrActions addObject:[SKAction playSoundFileNamed:@"regularTextBeep.m4a" waitForCompletion:YES]];
    [marrActions addObject:[SKAction waitForDuration:0.2]];
    [marrActions addObject:[SKAction runBlock:^{
        ((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).text = (NSString*)[_text substringToIndex:i];

        ((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).position = CGPointMake(20 + (((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).frame.size.width / 2.0), ((SKLabelNode*)[_scene childNodeWithName:@"insideOfTextBox"]).frame.size.height - (((SKLabelNode*)[_scene childNodeWithName:@"textBoxText"]).frame.size.height / 2.0) - 15);
        NSLog(@"Textbox loading a letter on iteration %u", i);
    }]];
}

[_scene runAction:[SKAction sequence:marrActions] completion:completion]; //Pass off the completion block here

I would also suggest this just to simplify that code:

SKLabelNode *textNode = (SKLabelNode*)[_scene childNodeWithName:@"textBoxText"];
SKLabelNode *insideOfTextNode = (SKLabelNode*)[_scene childNodeWithName:@"insideOfTextBox"];

textNode.text = [_text substringToIndex:i];
textNode.position = CGPointMake(20 + (textNode.frame.size.width / 2.0), insideOfTextNode.frame.size.height - (textNode.frame.size.height / 2.0) - 15);

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