1
votes

I got a turn based game, where objects move around the game board. This movement takes time, about 0.4 seconds per move. I would like to disable further touches on the scene until my object reaches its destination and I get to perform calculations for the new position.

I tried using boolean animation flags, but it seems that they are either ignored or are unreliable.

[selectedModel runAction:[SKAction moveTo:[MapOfTiles positionForTileCoord:s.position] duration:0.75] completion:^{
    [self animateNextMove];
    if(reachedDestination)
    {
        isAnimatingMove = NO;
    }
}];

I noticed that overlaying a transparent SpriteNode with user interaction set to NO seems to still capture touches (I was planning on adding a transparent overlay and setting it's user interaction on/off to capture touches.

What is the best way to disable buttons and touches on nodes while Sprite Kit performs some animation?

3

3 Answers

0
votes

Do [self setUserInteractionEnabled:NO]; on your scene:

[selectedModel runAction:[SKAction moveTo:[MapOfTiles positionForTileCoord:s.position] duration:0.75] completion:^{
    [self animateNextMove];
    [self setUserInteractionEnabled:NO];
    if(reachedDestination)
    {
        [self setUserInteractionEnabled:YES];
    }
}];

This will prevent all touches on your scene until reachedDestination becomes true...Is that what you were looking for?

0
votes

This appears to work:

cover is an instance variable node, when it is added to the scene, it does not allow touches to pass through. You may need to fiddle with your scene's size, mine is landscape.

-(void)preventUserInteraction:(BOOL)prevent
{
    if(cover == nil)
    {
        cover = [[SKSpriteNode alloc] initWithColor:[UIColor clearColor] size:CGSizeMake(1024,768 )];
        cover.position = CGPointMake(1024/2, 768/2);
    }
    if(prevent)
    {
        [self addChild:cover];
    }else
    {
        [cover removeFromParent];
    }
}
0
votes

Here's how I did it:

//Disable user interaction
[self setUserInteractionEnabled: NO];

// Grab our hero sprite node, create an image atlas of textures and push into an action
SKSpriteNode *hero = (SKSpriteNode *)[self childNodeWithName: @"hero"];

SKTextureAtlas *heroPunchAtlas = [SKTextureAtlas atlasNamed: @"heroPunch"];

SKTexture *punchF1 = [heroPunchAtlas textureNamed: @"heroPunchF1"];
SKTexture *punchF2 = [heroPunchAtlas textureNamed: @"heroPunchF2"];

NSArray *heroPunchTextures = @[punchF1, punchF2];

SKAction *heroPunch = [SKAction animateWithTextures: heroPunchTextures timePerFrame: 0.1];

// The trick is here, where you have the completion callback 
// which is fired once the animation is done. If you place the 
// [self setUserInteractionEnabled: YES]; as the last line, it will get called
// before the animation finishes (clock cycles run faster than animation).
[hero runAction: hulkPunch completion: ^(void){
    [self setUserInteractionEnabled: YES];
}];