Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Can I get keyboard input in a SpriteKit Game?

I'm a beginner in SpriteKit programming, and have been trying to figure out how to handle input from the keyboard.

What I've found so far is that you should subclass NSResponder and implement it like this:

@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 a few more methods/properties in the interface and implementation of AppDelegate but I didn't put them there to keep the question relevant.

Next, I would start using key codes to detect which keys are being pressed, but the keyUp and keyDown methods don't even get called. I'm not sure why.

Any Help?

Update: Thanks for your answers! I discovered that you have to implement keyUp and keyDown directly in your scene class, because they won't get called from the AppDelegate. Thanks again for the help!

like image 236
Dovahkiin Avatar asked Apr 13 '14 23:04

Dovahkiin


2 Answers

The easiest way I know is to implement the keyDown method in your SKScene (and not directly in the AppDelegate). You don't have to subclass anything.

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

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

Then use the method handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp to check which key has been 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. I found it very usefull to learn SpriteKit :)

like image 50
Heyfara Avatar answered Oct 11 '22 12:10

Heyfara


Swift (2.0) version of HeyFara's answer. I've just popped "breaks" in where you would 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)
                }
            }
        }
    }
}
like image 44
rougeExciter Avatar answered Oct 11 '22 11:10

rougeExciter