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