How can I get keyboard input in a SpriteKit game?

I am starting to program SpriteKit and trying to figure out how to handle keyboard input.

What I have found so far is that you should subclass NSResponder and implement it as follows:

@interface AppDelegate : NSResponder <NSApplicationDelegate> -(void)keyUp:(NSEvent *)theEvent; -(void)keyDown:(NSEvent *)theEvent; @end @implementation AppDelegate -(void)keyUp:(NSEvent *)theEvent { NSLog(@"Key Released"); } -(void)keyDown:(NSEvent *)theEvent { NSLog(@"Key Pressed"); } @end 

Obviously, there are several methods / properties in the AppDelegate interface and implementation, but I did not AppDelegate them there to save the corresponding question.

Then I will start using key codes to determine which keys are pressed, but the keyUp and keyDown methods keyUp not even called. I'm not sure why.

Any help?

Update: Thanks for your answers! I found that you need to implement keyUp and keyDown directly in your scene class, because they will not be called from AppDelegate. Thanks again for your help!

+7
objective-c sprite-kit macos
source share
3 answers

The easiest way is to implement the keyDown method in SKScene (and not directly in AppDelegate). You do not need to subclass anything.

 - (void)keyDown:(NSEvent *)event { [self handleKeyEvent:event keyDown:YES]; } - (void)keyUp:(NSEvent *)event { [self handleKeyEvent:event keyDown:NO]; } 

Then use the handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp to check which key was pressed:

 - (void)handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp { // First check the arrow keys since they are on the numeric keypad. if ([event modifierFlags] & NSNumericPadKeyMask) { // arrow keys have this mask NSString *theArrow = [event charactersIgnoringModifiers]; unichar keyChar = 0; if ([theArrow length] == 1) { keyChar = [theArrow characterAtIndex:0]; switch (keyChar) { case NSUpArrowFunctionKey: self.defaultPlayer.moveForward = downOrUp; break; case NSLeftArrowFunctionKey: self.defaultPlayer.moveLeft = downOrUp; break; case NSRightArrowFunctionKey: self.defaultPlayer.moveRight = downOrUp; break; case NSDownArrowFunctionKey: self.defaultPlayer.moveBack = downOrUp; break; } } } // Now check the rest of the keyboard NSString *characters = [event characters]; for (int s = 0; s<[characters length]; s++) { unichar character = [characters characterAtIndex:s]; switch (character) { case 'w': self.defaultPlayer.moveForward = downOrUp; break; case 'a': self.defaultPlayer.moveLeft = downOrUp; break; case 'd': self.defaultPlayer.moveRight = downOrUp; break; case 's': self.defaultPlayer.moveBack = downOrUp; break; case ' ': self.defaultPlayer.fireAction = downOrUp; break; } } } 

I took this code from the Apple SpriteKit Adventure game. It was very useful for me to learn SpriteKit :)

+11
source share

Swift (2.0) version of HeyFara's answer. I just clicked โ€œbreaksโ€ where you could make your actual function calls.

  public override func keyDown(theEvent: NSEvent) { handleKeyEvent(theEvent, keyDown: true) } public override func keyUp(theEvent: NSEvent) { handleKeyEvent(theEvent, keyDown: false) } public func handleKeyEvent(event:NSEvent, keyDown:Bool){ if event.modifierFlags.contains(NSEventModifierFlags.NumericPadKeyMask){ if let theArrow = event.charactersIgnoringModifiers, keyChar = theArrow.unicodeScalars.first?.value{ switch Int(keyChar){ case NSUpArrowFunctionKey: break case NSDownArrowFunctionKey: break case NSRightArrowFunctionKey: break case NSLeftArrowFunctionKey: break default: break } } } else { if let characters = event.characters{ for character in characters.characters{ switch(character){ case "w": break default: print(character) } } } } } 
+5
source share

If you want to know when a key is pressed, you must subscribe to the global event dispatcher.

 [NSEvent addGlobalMonitorForEventsMatchingMask:(NSKeyDownMask) handler:^(NSEvent *event) { [NSEvent removeMonitor:event]; 

This will call the handler when the key is pressed.

0
source share

All Articles