2013-11-15 2 views
15

Я делаю игру, и я хочу иметь кнопку. Как обращаться с ним? Я использую отдельный класс для пользовательского интерфейса, это SKSpriteNode, который содержит все кнопки и элементы интерфейса, и я не хочу, чтобы Сцена обрабатывала эти нажатия кнопок для меня с помощью метода начатых шагов.Правильный способ создания кнопки в наборе спрайтов?

Как я знаю, мы можем проверить, что узел, который тронут в касаниях, начался, поэтому для реализации обычной кнопки с прикосновением внутрь мне нужно написать код в touchhesBegan и touchhesEnded, это выглядит немного переборщиком.

Или использовать обычный UIButton? Но я знаю, что вы не можете добавить их динамически, только в методе didMoveToView, и это выглядит плохо.

+0

Вам нужно будет использовать touchhesBegan/Ended, как еще вы получите сенсорный ввод? Один из способов сделать это: https://github.com/KoboldKit/KoboldKit/blob/master/KoboldKit/KoboldKitFree/Framework/Behaviors/UserInterface/KKButtonBehavior.m – LearnCocos2D

+0

мой пример кнопки переключения http://stackoverflow.com/questions/ 19688451/how-to-make-a-toggle-button-on-spritekit/19694729 # 19694729 – DogCoffee

+0

Что плохо для вас при добавлении UIButton в didMoveToView? Если он показывает бит, превышающий нагрузку на сцену, попробуйте установить параметр «pausesIncomingScene» или SKTransition, который вы используете для показа SKScene..I персона, используйте метод SKSpriteNode с помощью методов прикосновений ... – BSevo

ответ

11

Я нашел это онлайн некоторое время назад, любезно предоставлен членом, который по имени Graf, это хорошо работает для моих проблем.

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

@property (nonatomic, readonly) SEL actionTouchUpInside; 
@property (nonatomic, readonly) SEL actionTouchDown; 
@property (nonatomic, readonly) SEL actionTouchUp; 
@property (nonatomic, readonly, weak) id targetTouchUpInside; 
@property (nonatomic, readonly, weak) id targetTouchDown; 
@property (nonatomic, readonly, weak) id targetTouchUp; 

@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; // Designated Initializer 

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

/** Sets the target-action pair, that is called when the Button is tapped. 
"target" won't be retained. 
*/ 
- (void)setTouchUpInsideTarget:(id)target action:(SEL)action; 
- (void)setTouchDownTarget:(id)target action:(SEL)action; 
- (void)setTouchUpTarget:(id)target action:(SEL)action; 

@end 

И реализация

// 
// 
// Courtesy of Graf on Stack Overflow 
// 
// 
// 
#import "SKBButtonNode.h" 



@implementation SKBButtonNode 

#pragma mark Texture Initializer 

/** 
* Override the super-classes designated initializer, to get a properly set SKButton in every case 
*/ 
- (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]; 
} 

/** 
* This is the designated Initializer 
*/ 
- (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 Setting Target-Action pairs 

- (void)setTouchUpInsideTarget:(id)target action:(SEL)action { 
    _targetTouchUpInside = target; 
    _actionTouchUpInside = action; 
} 

- (void)setTouchDownTarget:(id)target action:(SEL)action { 
    _targetTouchDown = target; 
    _actionTouchDown = action; 
} 

- (void)setTouchUpTarget:(id)target action:(SEL)action { 
    _targetTouchUp = target; 
    _actionTouchUp = action; 
} 

#pragma - 
#pragma mark Setter overrides 

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

- (void)setIsSelected:(BOOL)isSelected { 
    _isSelected = isSelected; 
    if ([self selectedTexture] && [self isEnabled]) { 
     if (_isSelected) { 
      [self setTexture:_selectedTexture]; 
     } else { 
      [self setTexture:_normalTexture]; 
     } 
    } 
} 

#pragma - 
#pragma mark Touch Handling 

/** 
* This method only occurs, if the touch was inside this node. Furthermore if 
* the Button is enabled, the texture should change to "selectedTexture". 
*/ 
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if ([self isEnabled]) { 
     if (_actionTouchDown){ 
      [self.parent performSelectorOnMainThread:_actionTouchDown withObject:_targetTouchDown waitUntilDone:YES]; 
      [self setIsSelected:YES]; 
     } 
    } 
} 

/** 
* If the Button is enabled: This method looks, where the touch was moved to. 
* If the touch moves outside of the button, the isSelected property is restored 
* to NO and the texture changes to "normalTexture". 
*/ 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    if ([self isEnabled]) { 
     UITouch *touch = [touches anyObject]; 
     CGPoint touchPoint = [touch locationInNode:self.parent]; 

     if (CGRectContainsPoint(self.frame, touchPoint)) { 
      [self setIsSelected:YES]; 
     } else { 
      [self setIsSelected:NO]; 
     } 
    } 
} 

/** 
* If the Button is enabled AND the touch ended in the buttons frame, the 
* selector of the target is run. 
*/ 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    CGPoint touchPoint = [touch locationInNode:self.parent]; 

    if ([self isEnabled] && CGRectContainsPoint(self.frame, touchPoint)) { 
     if (_actionTouchUpInside){ 
      [self.parent performSelectorOnMainThread:_actionTouchUpInside withObject:_targetTouchUpInside waitUntilDone:YES]; 
     } 
    } 
    [self setIsSelected:NO]; 
     if (_actionTouchUp){ 
     [self.parent performSelectorOnMainThread:_actionTouchUp withObject:_targetTouchUp waitUntilDone:YES]; 
    } 
} 
@end 
+1

Хотел бы дать вам -1 для каждого использования из 'objc_msgSend'. – Sulthan

+0

Там, заменил все objc_msgSend() ' – Andrew97p

+0

@ Andrew97p, можете ли вы объяснить, пожалуйста, почему нам нужно выполнять селектор на self.parent, но не только на себя? – AndrewShmig

8

Я создал класс для использования SKSpriteNode в качестве кнопки довольно давно. Здесь вы можете найти его на GitHub.

AGSpriteButton

реализация Это основано на UIButton, так что если вы уже знакомы с прошивкой, вы должны найти его легко работать.

Он включает в себя метод настройки ярлыка.

Кнопка обычно объявляется следующим образом:

AGSpriteButton *button = [AGSpriteButton buttonWithColor:[UIColor redColor] andSize:CGSizeMake(300, 100)]; 
[button setLabelWithText:@"Button Text" andFont:nil withColor:nil]; 
button.position = CGPointMake(self.size.width/2, self.size.height/3); 
[button addTarget:self selector:@selector(someSelector) withObject:nil forControlEvent:AGButtonControlEventTouchUpInside]; 
[self addChild:button]; 

И это все. Тебе хорошо идти.

EDIT: После публикации этого ответа в AGSpriteButton было сделано несколько улучшений.

Теперь вы можете назначить блоки, которые будут выполняться на сенсорных событий:

[button performBlock:^{ 
     [self addSpaceshipAtPoint:[NSValue valueWithCGPoint:CGPointMake(100, 100)]]; 
    } onEvent:AGButtonControlEventTouchUp]; 

Кроме того, объект SKAction быть выполнены на примере SKNode (или любого из его подклассов) могут быть назначены:

[button addTarget:self 
     selector:@selector(addSpaceshipAtPoint:) 
     withObject:[NSValue valueWithCGPoint:CGPointMake(self.size.width/2, self.size.height/2)]   
     forControlEvent:AGButtonControlEventTouchUpInside]; 

AGSpriteButton также может использоваться с Swift!

let button = AGSpriteButton(color: UIColor.greenColor(), andSize: CGSize(width: 200, height: 60)) 
button.position = CGPoint(x: self.size.width/2, y: self.size.height/2) 
button.addTarget(self, selector: "addSpaceship", withObject: nil, forControlEvent:AGButtonControlEvent.TouchUpInside) 
button.setLabelWithText("Spaceship", andFont: nil, withColor: UIColor.blackColor()) 
addChild(button) 
+2

Вы должны использовать nil вместо Nil в своем коде. Ниль для пустого класса. – Dvole

+0

Спасибо @ Dvole. Будет обновляться. – ZeMoon

Смежные вопросы