注意:这适用于OS X应用,而非iOS应用。
我正在创建一个自定义按钮类,它是SKSpriteNode的子类。我希望这个类能够处理按钮按下,所以我发现我必须将setuserinteractionenabled设置为YES。当我在自定义按钮类中执行此操作以便mouseDown事件接收消息时,创建按钮的SKScene在单击按钮时不再接收消息。有没有办法解决这个问题?我甚至尝试在SKScene中启用setuserinteractionenabled,但无济于事。我找不到任何有关此问题的问题。
Button.h
#import <SpriteKit/SpriteKit.h>
typedef enum ButtonState {
UNPRESSED,
PRESSED
} ButtonState;
@interface Button : SKSpriteNode
@property ButtonState state;
-(id)initButtonWithImage:(NSString*)unselectedImage selectedImage:(NSString*)selectedImage;
-(void)setButtonState:(NSString*)event;
@end
Button.m(自定义按钮类)
#import "Button.h"
@interface Button()
@property SKSpriteNode *image;
@property SKSpriteNode *unselectedImage;
@property SKSpriteNode *selectedImage;
@end
@implementation Button
@synthesize state = _state;
@synthesize image = _image;
@synthesize unselectedImage = _unselectedImage;
@synthesize selectedImage = _selectedImage;
-(id)initButtonWithImage:(NSString*)unselectedImage selectedImage:(NSString*)selectedImage {
if (self = [super init]) {
_unselectedImage = [[SKSpriteNode alloc] initWithImageNamed:unselectedImage];
_selectedImage = [[SKSpriteNode alloc] initWithImageNamed:selectedImage];
_image = _unselectedImage;
_image.name = @"image";
[self addChild:_image];
self.userInteractionEnabled = YES;
}
return self;
}
-(void)setButtonState:(NSString*)event {
[self removeAllChildren];
if ([event isEqualToString:@"mousedown"])
_image = _selectedImage;
else if ([event isEqualToString:@"mouseup"])
_image = _unselectedImage;
[self addChild:_image];
}
-(void)mouseDown:(NSEvent *)theEvent {
[self setButtonState:@"mousedown"];
}
-(void)mouseUp:(NSEvent *)theEvent {
[self setButtonState:@"mouseup"];
}
@end
GameMenu.m(SKScene)
#import "GameMenu.h"
#import "NoteBlasterMenu.h"
#import "ChordAttackMenu.h"
#import "Button.h"
@implementation GameMenu
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.userInteractionEnabled = YES; //allows scene to register clicks
[self initBackground];
[self initButtons];
[self setUserInteractionEnabled:YES];
}
return self;
}
-(void) initBackground {
SKSpriteNode *bg = [SKSpriteNode spriteNodeWithImageNamed:@"menubg"];
bg.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:bg];
}
-(void) initButtons {
Button *chordAttackButton = [[Button alloc] initButtonWithImage:@"chordattackbutton"
selectedImage:@"chordattackbuttonpressed"];
chordAttackButton.position = CGPointMake(self.size.width/2, self.size.height/2);
chordAttackButton.name = @"chordAttackButton";
[self addChild:chordAttackButton];
Button *noteBlasterButton = [[Button alloc] initButtonWithImage:@"noteblasterbutton"
selectedImage:@"noteblasterbuttonpressed"];
noteBlasterButton.position = CGPointMake(self.size.width/2, self.size.height/2 - 150);
noteBlasterButton.name = @"noteBlasterButton";
[self addChild:noteBlasterButton];
}
-(void)mouseDown:(NSEvent *)theEvent {
CGPoint location = [theEvent locationInNode:self];
NSArray *nodes = [self nodesAtPoint:location];
NSLog(@"I'm being pressed");
for (SKNode *node in nodes) {
if ([node isKindOfClass:[Button class]]) {
Button *button = (Button*)node;
if ([button.name isEqualToString:@"chordAttackButton"]) {
SKScene *scene = [ChordAttackMenu sceneWithSize:CGSizeMake(1280, 720)];
[self.view presentScene:scene transition:[SKTransition fadeWithDuration:0.55]];
}
else if ([button.name isEqualToString:@"noteBlasterButton"]) {
SKScene *scene = [NoteBlasterMenu sceneWithSize:CGSizeMake(1280, 720)];
[self.view presentScene:scene transition:[SKTransition fadeWithDuration:0.55]];
}
}
}
}
@end
AppDelegate.m
....(header files etc)
@implementation AppDelegate
@synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
/* Set up the window for the app */
NSRect frame = [_window frame];
frame.size = CGSizeMake(1280, 740);
[_window setFrame: frame display: YES animate: NO];
[_window center]; //sets the window to the centre of the screen
/* Pick a size for the scene */
//SKScene *scene = [ChordAttackMenu sceneWithSize:CGSizeMake(1280, 720)]; //ChordAttack Menu
//SKScene *scene = [MyScene sceneWithSize:CGSizeMake(1280, 720)]; //ChordAttack
//SKScene *scene = [NoteBlasterMenu sceneWithSize:CGSizeMake(1280, 720)]; //BassBlaster Menu
//SKScene *scene = [NoteBlaster sceneWithSize:CGSizeMake(1280, 720)]; //BassBlaster
SKScene *scene = [GameMenu sceneWithSize:CGSizeMake(1280, 720)];
/* Set the scale mode to scale to fit the window */
//scene.scaleMode = SKSceneScaleModeAspectFit;
scene.scaleMode = SKSceneScaleModeAspectFill;
[self.skView presentScene:scene];
self.skView.showsFPS = YES;
self.skView.showsNodeCount = YES;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return YES;
}
答案 0 :(得分:1)
在GameMenu.m的initButtons方法中,为每个按钮设置下一个响应者
chordAttackButton.nextResponder = self;
noteBlasterButton.nextResponder = self;
在Button类中,通过
将鼠标向下/向上传递到响应者链中-(void)mouseDown:(NSEvent *)theEvent {
[self setButtonState:@"mousedown"];
[super mouseDown:theEvent];
}
-(void)mouseUp:(NSEvent *)theEvent {
[self setButtonState:@"mouseup"];
[super mouseUp:theEvent];
}
答案 1 :(得分:0)
所以这很奇怪。你可以说,我不是最好的Objective c。但是在处理事件之后,根据apple Event Handling Guide,您可以使用
将其传递给响应者链[super theEvent];
但在这种情况下,GameScene是父按钮而不是其超视图。所以,你需要做的是像这样调用事件:
[self.parent theEvent];
或
[self setNextResponder:referenceToGameScene];
[self.nextResponder theEvent];
最好让控制器以较少复杂的方式管理这些事件。因为每个孩子都补充说你想要传递事件,响应者链需要实现上面的代码。