02fentym
02fentym

Reputation: 1792

Global key handler for SpriteKit Game

I currently have all of my key press code in my various SKScene classes. I only want something to happen every time the key is pressed. The key needs to be re-triggered to perform the action again. I'm using a boolean array to keep track of this. This may not be optimal, but it's what I thought of at the time. I was looking to create a class to manage all of this, but key event methods keyUp and keyDown are created in SKScene classes. Is there a global way to handle keys presses so that I don't have to recreate this code in every scene in my game?

Upvotes: 0

Views: 329

Answers (2)

0x141E
0x141E

Reputation: 12773

You can subclass SKView and perform all your key press handling in a centralized location. This approach has several benefits: 1. since all key press logic is in a single class, changes to the logic are made to that class instead of in all of your scenes and 2) it removes device-specific input logic from the multiple scenes. If you decide to port your app to iOS, for example, you can simply change the interface from the keyboard/mouse to touches in a single file.

The following is an implementation of a key press handler in a custom subclass of SKView. It uses a protocol/delegate design pattern to send key press messages to the various scenes. Delegation is a convenient way for an object (in this case a class) to communication with other classes and the protocol defines how this communication will take place.

  1. Create a subclass of SKView

CustomSKView.h

@protocol KeyPressedDelegate;

@interface CustomSKView : SKView

@property (weak) id <KeyPressedDelegate> delegate;

@end

@protocol KeyPressedDelegate

- (void) upArrowPressed;
- (void) downArrowPressed;

@end

CustomSKView.m

All the key press handling logic resides here. The details of how key presses are handled are hidden from the code that acts on the key presses.

@implementation CustomSKView:SKView {
    // Add instance variables here
}

// This is called when the view is created.
- (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:
                [self.delegate upArrowPressed];
                break;
            case 125:
                [self.delegate downArrowPressed];
                break;
            default:
                break;
        }
    }
}

@end
  1. Adopt the protocol

GameScene.h

#import "CustomSKView.h"

@interface GameScene : SKScene <KeyPressedDelegate>

@end
  1. Implement the delegate method in all scenes that require key press info

GameScene.m

@implementation GameScene

-(void)didMoveToView:(SKView *)view {
    ((CustomSKView *)view).delegate = self;
}

- (void) upArrowPressed {
    NSLog(@"Up Arrow Pressed");
}
- (void) downArrowPressed {
    NSLog(@"Down Arrow Pressed");
}

@end
  1. In your main .xib file, set the class for your SKView to the custom class:

enter image description here

enter image description here

Upvotes: 2

mert
mert

Reputation: 1098

I recommend to using Singleton pattern to store and fetch your keys. Because you can reach from your SKScene and than create or update any time.

http://www.galloway.me.uk/tutorials/singleton-classes/ this singleton intro is fast and short.

Upvotes: 0

Related Questions