0

I used a solution from this question SpriteKit Objective-C: programming directional pad controls as well as a version of custom class buttons from here Correct way to create button in Sprite Kit? with omitted target-action methods to create virtual control buttons for my SpriteKit game. So here is the problem: what I am trying to implement is two separate sets of buttons unrelated to each other (for instance, D-pad on the left, and fire buttons on the right) and the ability to use them both at the same time with help of multi-touch, just like you would on a hardware controller with action buttons on the right and dirs on the left. So let's imagine the situation:

1) I start by holding a directional button and a fire button. Then I drag my left finger outside the directional button, which triggers the if(node.name)'s ELSE statement, that sets all buttons' "selected" bools to NO. This is not what I want because the fire button is still held, and it should retain it's "selected" state, while directional button — shouldn't.

2) Same situation, but if I drag my right finger outside the fire button instead, and keep holding directional button. Both buttons get "deselected", when fire button shouldn't do it.

So how do I implement it correctly with a way to detect, which button exactly got "deselected" to "deselect" just that particular set of buttons? Please push me in the right direction. Hope what I have requested is possible.

Current code (It's pretty messy, excuse the gorilla-style coding):

DirectionalButton.h

#import <SpriteKit/SpriteKit.h>
@interface DirectionalButton : SKSpriteNode

@property (nonatomic) BOOL isEnabled;
@property (nonatomic) BOOL isSelected;
@property (nonatomic, readonly, strong) SKLabelNode *title;
@property (nonatomic, readwrite, strong) SKTexture *normalTexture;
@property (nonatomic, readwrite, strong) SKTexture *selectedTexture;
@property (nonatomic, readwrite, strong) SKTexture *disabledTexture;

- (instancetype)initWithTextureNormal:(SKTexture *)normal selected:(SKTexture *)selected;

- (instancetype)initWithTextureNormal:(SKTexture *)normal selected:(SKTexture *)selected disabled:(SKTexture *)disabled;

- (instancetype)initWithImageNamedNormal:(NSString *)normal selected:(NSString *)selected;
- (instancetype)initWithImageNamedNormal:(NSString *)normal selected:(NSString *)selected disabled:(NSString *)disabled;

@end

DirectionalButton.m

#import "DirectionalButton.h"



@implementation DirectionalButton

#pragma mark Texture Initializer

- (instancetype)initWithTexture:(SKTexture *)texture color:(UIColor *)color size:(CGSize)size {
    return [self initWithTextureNormal:texture selected:nil disabled:nil];
}

- (instancetype)initWithTextureNormal:(SKTexture *)normal selected:(SKTexture *)selected {
    return [self initWithTextureNormal:normal selected:selected disabled:nil];
}

- (instancetype)initWithTextureNormal:(SKTexture *)normal selected:(SKTexture *)selected disabled:(SKTexture *)disabled {
    self = [super initWithTexture:normal color:[UIColor whiteColor] size:normal.size];
    if (self) {
        [self setNormalTexture:normal];
        [self setSelectedTexture:selected];
        [self setDisabledTexture:disabled];
        [self setIsEnabled:YES];
        [self setIsSelected:NO];

        _title = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
        [_title setVerticalAlignmentMode:SKLabelVerticalAlignmentModeCenter];
        [_title setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeCenter];

        [self addChild:_title];
        [self setUserInteractionEnabled:YES];
    }
    return self;
}

#pragma mark Image Initializer

- (instancetype)initWithImageNamedNormal:(NSString *)normal selected:(NSString *)selected {
    return [self initWithImageNamedNormal:normal selected:selected disabled:nil];
}

- (instancetype)initWithImageNamedNormal:(NSString *)normal selected:(NSString *)selected disabled:(NSString *)disabled {
    SKTexture *textureNormal = nil;
    if (normal) {
        textureNormal = [SKTexture textureWithImageNamed:normal];
    }

    SKTexture *textureSelected = nil;
    if (selected) {
        textureSelected = [SKTexture textureWithImageNamed:selected];
    }

    SKTexture *textureDisabled = nil;
    if (disabled) {
        textureDisabled = [SKTexture textureWithImageNamed:disabled];
    }

    return [self initWithTextureNormal:textureNormal selected:textureSelected disabled:textureDisabled];
}


#pragma -
#pragma mark Setter overrides

- (void)setIsEnabled:(BOOL)isEnabled {
    _isEnabled = isEnabled;
    if ([self disabledTexture]) {
        if (!_isEnabled) {
            [self setTexture:_disabledTexture];
        } else {
            [self setTexture:self.normalTexture];
        }
    }
}

- (void)setIsSelected:(BOOL)isSelected {
    _isSelected = isSelected;
    if ([self selectedTexture] && [self isEnabled]) {
        if (_isSelected) {
            [self setTexture:_selectedTexture];
            [self runAction:[SKAction fadeAlphaTo:0.55 duration:0.12f]];
        } else {
            [self setTexture:self.normalTexture];
            [self runAction:[SKAction fadeAlphaTo:1 duration:0.12f]];
        }
    }
}
@end

GameScene.m

- (void)createHUD {
//Executed in didMoveToView
NSString *pathToImageForLeftButtonTexture = @"buttonDirectionalLeft";
NSString *pathToImageForRightButtonTexture = @"buttonDirectionalRight";
dirBtnLeft = [[DirectionalButton alloc]initWithImageNamedNormal:pathToImageForLeftButtonTexture selected:pathToImageForLeftButtonTexture];
/*
    Set size and position for left
*/
dirBtnLeft.name = @"directionalLeft";
dirBtnRight = [[DirectionalButton alloc]initWithImageNamedNormal:pathToImageForRightButtonTexture selected:pathToImageForRightButtonTexture];
/*
    Set size and position accordingly to left button for right
*/
dirBtnRight.name = @"directionalRight";
dirBtnLeftFrame = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:dirBtnLeft.size];
dirBtnLeftFrame.position = dirBtnLeft.position;
dirBtnRightFrame = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:dirBtnRight.size];
fireBtn = [[DirectionalButton alloc]initWithImageNamedNormal:@"default.jpg" selected:@"default.jpg"];
/*
    Set position and size for fire
*/
fireBtnFrame = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:fireBtn.size];
fireBtnFrame.position = fireBtn.position;
dirBtnRightFrame.position = dirBtnRight.position;
dirBtnLeftFrame.zPosition = 100;
dirBtnRightFrame.zPosition = 100;
fireBtnFrame.zPosition = 100;
dirBtnRight.zPosition = 99;
dirBtnLeft.zPosition = 99;
fireBtn.zPosition = 99;
dirBtnLeftFrame.name = @"directionalLeftFrame";
dirBtnRightFrame.name = @"directionalRightFrame";
fireBtnFrame.name = @"primaryFire";
[self addChild:dirBtnLeft];
[self addChild:dirBtnRight];
[self addChild:dirBtnLeftFrame];
[self addChild:dirBtnRightFrame];
[self addChild:fireBtn];
[self addChild:fireBtnFrame];    
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesMoved:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *touch in [event allTouches]){
    CGPoint touchLocation = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:touchLocation];


    if (node.name)
    {
        if ([node.name isEqualToString:@"directionalRightFrame"])
        {

            if(!dirBtnRight.isSelected){
            [dirBtnRight setIsSelected:YES];
                [dirBtnLeft setIsSelected:NO];}
        }
        else if ([node.name isEqualToString:@"directionalLeftFrame"])
        {
            if(!dirBtnLeft.isSelected){
            [dirBtnRight setIsSelected:NO];
                [dirBtnLeft setIsSelected:YES];}
        }
        else if ([node.name isEqualToString:@"primaryFire"]) {
            if (!fireBtn.isSelected) {
                [fireBtn setIsSelected:YES];
            }
        }
    }
    else
    {
        [dirBtnRight setIsSelected:NO];
        [dirBtnLeft setIsSelected:NO];
        [fireBtn setIsSelected:NO];
    }}
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in [event allTouches]) {
    CGPoint touchPoint = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:touchPoint];
    if(node.name){
    if ([node.name isEqualToString:@"directionalLeftFrame"]) {
dirBtnLeft.isSelected = NO;}
else if ([node.name isEqualToString:@"directionalRightFrame"])
{
    dirBtnRight.isSelected = NO;
}
else if([node.name isEqualToString:@"primaryFire"]){
    fireBtn.isSelected = NO;}
    }    else
    {
        dirBtnLeft.isSelected = NO;
        dirBtnRight.isSelected = NO;
        fireBtn.isSelected = NO;}}
}

-(void)update:(CFTimeInterval)currentTime {
    if(dirBtnLeft.isSelected){
        //Do something
    }
    else if(dirBtnRight.isSelected){
        //Do something else
    }
    else
    {
        //Stop doing anything
    }
}
Community
  • 1
  • 1

1 Answers1

0

In touchesEnded you are looping through all the active touches in the SKScene.
[event allTouches] returns all the active touches.
Instead of that just use the touches NSSet to loop through the touches that have actually ended.

Use the following code instead in touchesMoved and touchesEnded.

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
     for (UITouch *touch in touches) {
          // Your conditions
     }
}
rakeshbs
  • 24,392
  • 7
  • 73
  • 63
  • Got the following problem with this (I can only test it in iOS Simulator, so I placed it so that I can hold them both at the same time with the alt-clicking): 1) Start by holding both dir. and fire at the same time. 2) Move the touches so that fire button is no longer pressed while right button is. 3) Both buttons get "deselected". This occurs exactly at a 1/3 piece of the dir. button. But the problem will not be there if I alt-click the fire button first, and not the dir. one. What can be wrong? –  Mar 25 '15 at 11:05
  • so what's the problem? – rakeshbs Mar 25 '15 at 11:06
  • Yes, I did. Still no luck. –  Mar 25 '15 at 11:31
  • Also, **sometimes** it does not detect anything if you alt-click it so that one of the touches is on the button, and the other touch is somewhere away. I think the cause might be the parsing issue, since one of the touches happens slightly before than the other, because it happens randomly. –  Mar 25 '15 at 11:50
  • were you able to fix the problem? It might be something to do with your `if` conditions. – rakeshbs Mar 27 '15 at 00:54