SpriteKit Keyboard Observer
I am currently using delegation and a custom SKView class to control keystrokes in my OS X SpriteKit game. I need to use multiple delegates for my keyboard control class, which I know is not possible, but it is possible with observers. How can I do that? Here's my code using the delegation pattern:
CustomSKView.h
#import <SpriteKit/SpriteKit.h>
@protocol KeyPressedDelegate;
@interface CustomSKView : SKView
@property (weak) id <KeyPressedDelegate> delegate;
@end
@protocol KeyPressedDelegate
- (void) upArrowPressed;
- (void) downArrowPressed;
@end
CustomSKView.m
#import "CustomSKView.h"
@implementation CustomSKView:SKView {
// Add instance variables here
}
- (id) initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
// Allocate and initialize your instance variables here
}
return self;
}
- (void) keyDown:(NSEvent *)theEvent {
// Add code to handle a key down event here
if (self.delegate) {
switch (theEvent.keyCode) {
case 126: {
NSLog(@"delegate = %@", [self delegate]);
[self.delegate upArrowPressed];
break;
}
case 125:
[self.delegate downArrowPressed];
break;
default:
break;
}
}
}
@end
GameScene.h
#import <SpriteKit/SpriteKit.h>
#import "CustomSKView.h"
@interface GameScene : SKScene <KeyPressedDelegate>
@end
GameScene.m
#import "GameScene.h"
@implementation GameScene
-(void)didMoveToView:(SKView *)view {
((CustomSKView *)view).delegate = self;
}
- (void) upArrowPressed {
NSLog(@"Up Arrow Pressed");
}
- (void) downArrowPressed {
NSLog(@"Down Arrow Pressed");
}
@end
source to share
You are looking for NSNotificationCenter
. To add an object as an observer, use the following:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyPressed:)
name:@"KeyPressedNotificationKey"
object:nil];
This causes the object to watch for named notifications @"KeyPressedNotificationKey"
. To send a notification with this name and attach the keyCode to the key pressed, call this:
[[NSNotificationCenter defaultCenter] postNotificationName:@"KeyPressedNotificationKey"
object:nil
userInfo:@{@"keyCode" : @(event.keyCode)];
When you post a notification, any observers will call the method associated with the observer. You can get the keyCode from the dictionary userInfo
you attached when you sent the notification. In this case, the method with this signature will be called:
- (void)keyPressed:(NSNotification *)notification
{
NSNumber *keyCodeObject = notification.userInfo[@"keyCode"];
NSInteger keyCode = keyCodeObject.integerValue;
// Do your thing
}
There is one catch. You need to remove the object as an observer as soon as it happens by observing. If you delete the object without removing the observer, then post a notification, it will still try to call a method on a non-existent object and fail. Use the following code to remove an object as an observer:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"NotificationNameKey"
object:nil];
source to share