johnrspicer
johnrspicer

Reputation: 61

How to make an animated button in Sprite Kit

I have been trying to implement a method where the user can press down the play button, it then changes the texture to the pressed down image. Then, if the user decides not to continue with their action. Such as starting the game. They can then simply drag out of the sprite's frame/body which will then no longer detect the touch as one which will start the action.

The problem with this implementation is that I can't make the touch on the button cancel if the user drags outside of the play button's sprite frame.

The code you will see below doesn't have the transition between the scenes, as I'd like to test the button's usability before having to always quit the application to try the button.

Also, I have declared the majority of objects in the .h file.

Code from MenuScene.m:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //Touch detection declaration
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];
    touchNode = [self nodeAtPoint:touchLocation];

    if([touchNode.name isEqualToString:@"playButton"]){
        [playButtonSprite runAction:changePlayButtonTextureON];
    }else{}

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    if ([touchNode.name isEqualToString:@"playButton"]) {
        [playButtonSprite runAction:changePlayButtonTextureOFF];
    }
}

I would also like to know if there is an alternative method to detecting if the touch is on the play button sprite node. Though, this may be solved when a solution is found for the previous issue I have mentioned.

Upvotes: 1

Views: 698

Answers (2)

Leeroy Ding
Leeroy Ding

Reputation: 94

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //Touch detection declaration
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];
    touchNode = [self nodeAtPoint:touchLocation];

    if([touchNode.name isEqualToString:@"playButton"]){
        [playButtonSprite runAction:changePlayButtonTextureON];
        playButtonSprite.isON = YES;
    }else{}
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (playButtonSprite.isON) {
        if ([touchNode.name isEqualToString:@"playButton"]) {  // The user really wants to play!
            [self startPlaying];
        }
        [playButtonSprite runAction:changePlayButtonTextureOFF];
        playButtonSprite.isON = NO;
    }
}

Where changePlayButtonTextureON also sets playButtonSprite.isON to YES, and vise versa.

You will want to make a subclass of SKSpriteNode for playButtonSprite, and add that boolean property isON there.

Upvotes: 0

ZeMoon
ZeMoon

Reputation: 20284

The best way to handle this would be to subclass SKSpriteNode to handle touches on it's own. You can see such an implementation in this project on GitHub. It cancels the touch when the touch goes out of the node's bounds.

The existing code you have posted is good as the code will not get called when the touch ends out of the play button's bounds.

In your case, since you are handling the touches from the scene itself, you can explicitly set the playButton's texture whenever the touch is detected outside the node's bounds.

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];
    touchNode = [self nodeAtPoint:touchLocation];

    if(![touchNode.name isEqualToString:@"playButton"]){
        [playButtonSprite runAction:changePlayButtonTextureOFF];
    }
}

Upvotes: 1

Related Questions