Skip to content

Instantly share code, notes, and snippets.

@figgleforth
Last active January 13, 2022 13:18
Show Gist options
  • Select an option

  • Save figgleforth/adaf1bba2b8c106639c3 to your computer and use it in GitHub Desktop.

Select an option

Save figgleforth/adaf1bba2b8c106639c3 to your computer and use it in GitHub Desktop.
Keyboard input for use with SpriteKit or SceneKit
//
// Keyboard.swift
//
// Created by Bojan Percevic on 5/21/15.
// Copyright (c) 2015 Bojan Percevic. All rights reserved.
//
import AppKit
enum KeyCode: CUnsignedShort {
case A = 0x00
case S = 0x01
case D = 0x02
case F = 0x03
case H = 0x04
case G = 0x05
case Z = 0x06
case X = 0x07
case C = 0x08
case V = 0x09
case B = 0x0B
case Q = 0x0C
case W = 0x0D
case E = 0x0E
case R = 0x0F
case Y = 0x10
case T = 0x11
case One = 0x12
case Two = 0x13
case Three = 0x14
case Four = 0x15
case Six = 0x16
case Five = 0x17
case Equals = 0x18
case Nine = 0x19
case Seven = 0x1A
case Minus = 0x1B
case Eight = 0x1C
case Zero = 0x1D
case RightBracket = 0x1E
case O = 0x1F
case U = 0x20
case LeftBracket = 0x21
case I = 0x22
case P = 0x23
case L = 0x25
case J = 0x26
case Quote = 0x27
case K = 0x28
case Semicolon = 0x29
case Backslash = 0x2A
case Comma = 0x2B
case Slash = 0x2C
case N = 0x2D
case M = 0x2E
case Period = 0x2F
case Grave = 0x32
case KeypadDecimal = 0x41
case KeypadMultiply = 0x43
case KeypadPlus = 0x45
case KeypadClear = 0x47
case KeypadDivide = 0x4B
case KeypadEnter = 0x4C
case KeypadMinus = 0x4E
case KeypadEquals = 0x51
case KeypadZero = 0x52
case KeypadOne = 0x53
case KeypadTwo = 0x54
case KeypadThree = 0x55
case KeypadFour = 0x56
case KeypadFive = 0x57
case KeypadSix = 0x58
case KeypadSeven = 0x59
case KeypadEight = 0x5B
case KeypadNine = 0x5C
case Return = 0x24
case Tab = 0x30
case Space = 0x31
case Delete = 0x33
case Escape = 0x35
case Command = 0x37
case LeftShift = 0x38
case CapsLock = 0x39
case LeftOption = 0x3A
case LeftControl = 0x3B
case RightShift = 0x3C
case RightOption = 0x3D
case RightControl = 0x3E
case Function = 0x3F
case F17 = 0x40
case VolumeUp = 0x48
case VolumeDown = 0x49
case Mute = 0x4A
case F18 = 0x4F
case F19 = 0x50
case F20 = 0x5A
case F5 = 0x60
case F6 = 0x61
case F7 = 0x62
case F3 = 0x63
case F8 = 0x64
case F9 = 0x65
case F11 = 0x67
case F13 = 0x69
case F16 = 0x6A
case F14 = 0x6B
case F10 = 0x6D
case F12 = 0x6F
case F15 = 0x71
case Help = 0x72
case Home = 0x73
case PageUp = 0x74
case ForwardDelete = 0x75
case F4 = 0x76
case End = 0x77
case F2 = 0x78
case PageDown = 0x79
case F1 = 0x7A
case Left = 0x7B
case Right = 0x7C
case Down = 0x7D
case Up = 0x7E
}
struct KeyboardState {
var keys: [CUnsignedShort:Bool] = [
KeyCode.A.rawValue : false,
KeyCode.S.rawValue : false,
KeyCode.D.rawValue : false,
KeyCode.F.rawValue : false,
KeyCode.H.rawValue : false,
KeyCode.G.rawValue : false,
KeyCode.Z.rawValue : false,
KeyCode.X.rawValue : false,
KeyCode.C.rawValue : false,
KeyCode.V.rawValue : false,
KeyCode.B.rawValue : false,
KeyCode.Q.rawValue : false,
KeyCode.W.rawValue : false,
KeyCode.E.rawValue : false,
KeyCode.R.rawValue : false,
KeyCode.Y.rawValue : false,
KeyCode.T.rawValue : false,
KeyCode.One.rawValue : false,
KeyCode.Two.rawValue : false,
KeyCode.Three.rawValue : false,
KeyCode.Four.rawValue : false,
KeyCode.Six.rawValue : false,
KeyCode.Five.rawValue : false,
KeyCode.Equals.rawValue : false,
KeyCode.Nine.rawValue : false,
KeyCode.Seven.rawValue : false,
KeyCode.Minus.rawValue : false,
KeyCode.Eight.rawValue : false,
KeyCode.Zero.rawValue : false,
KeyCode.RightBracket.rawValue : false,
KeyCode.O.rawValue : false,
KeyCode.U.rawValue : false,
KeyCode.LeftBracket.rawValue : false,
KeyCode.I.rawValue : false,
KeyCode.P.rawValue : false,
KeyCode.L.rawValue : false,
KeyCode.J.rawValue : false,
KeyCode.Quote.rawValue : false,
KeyCode.K.rawValue : false,
KeyCode.Semicolon.rawValue : false,
KeyCode.Backslash.rawValue : false,
KeyCode.Comma.rawValue : false,
KeyCode.Slash.rawValue : false,
KeyCode.N.rawValue : false,
KeyCode.M.rawValue : false,
KeyCode.Period.rawValue : false,
KeyCode.Grave.rawValue : false,
KeyCode.KeypadDecimal.rawValue : false,
KeyCode.KeypadMultiply.rawValue : false,
KeyCode.KeypadPlus.rawValue : false,
KeyCode.KeypadClear.rawValue : false,
KeyCode.KeypadDivide.rawValue : false,
KeyCode.KeypadEnter.rawValue : false,
KeyCode.KeypadMinus.rawValue : false,
KeyCode.KeypadEquals.rawValue : false,
KeyCode.KeypadZero.rawValue : false,
KeyCode.KeypadOne.rawValue : false,
KeyCode.KeypadTwo.rawValue : false,
KeyCode.KeypadThree.rawValue : false,
KeyCode.KeypadFour.rawValue : false,
KeyCode.KeypadFive.rawValue : false,
KeyCode.KeypadSix.rawValue : false,
KeyCode.KeypadSeven.rawValue : false,
KeyCode.KeypadEight.rawValue : false,
KeyCode.KeypadNine.rawValue : false,
KeyCode.Return.rawValue : false,
KeyCode.Tab.rawValue : false,
KeyCode.Space.rawValue : false,
KeyCode.Delete.rawValue : false,
KeyCode.Escape.rawValue : false,
KeyCode.Command.rawValue : false,
KeyCode.LeftShift.rawValue : false,
KeyCode.CapsLock.rawValue : false,
KeyCode.LeftOption.rawValue : false,
KeyCode.LeftControl.rawValue : false,
KeyCode.RightShift.rawValue : false,
KeyCode.RightOption.rawValue : false,
KeyCode.RightControl.rawValue : false,
KeyCode.Function.rawValue : false,
KeyCode.F17.rawValue : false,
KeyCode.VolumeUp.rawValue : false,
KeyCode.VolumeDown.rawValue : false,
KeyCode.Mute.rawValue : false,
KeyCode.F18.rawValue : false,
KeyCode.F19.rawValue : false,
KeyCode.F20.rawValue : false,
KeyCode.F5.rawValue : false,
KeyCode.F6.rawValue : false,
KeyCode.F7.rawValue : false,
KeyCode.F3.rawValue : false,
KeyCode.F8.rawValue : false,
KeyCode.F9.rawValue : false,
KeyCode.F11.rawValue : false,
KeyCode.F13.rawValue : false,
KeyCode.F16.rawValue : false,
KeyCode.F14.rawValue : false,
KeyCode.F10.rawValue : false,
KeyCode.F12.rawValue : false,
KeyCode.F15.rawValue : false,
KeyCode.Help.rawValue : false,
KeyCode.Home.rawValue : false,
KeyCode.PageUp.rawValue : false,
KeyCode.ForwardDelete.rawValue : false,
KeyCode.F4.rawValue : false,
KeyCode.End.rawValue : false,
KeyCode.F2.rawValue : false,
KeyCode.PageDown.rawValue : false,
KeyCode.F1.rawValue : false,
KeyCode.Left.rawValue : false,
KeyCode.Right.rawValue : false,
KeyCode.Down.rawValue : false,
KeyCode.Up.rawValue : false,
]
}
class Keyboard {
var prev: KeyboardState = KeyboardState()
var curr: KeyboardState = KeyboardState()
func handleKey(event: NSEvent, isDown: Bool) {
if (isDown) {
curr.keys[event.keyCode] = true
} else {
curr.keys[event.keyCode] = false
}
}
func justPressed(keys: KeyCode...) -> Bool {
for key in keys {
if (curr.keys[key.rawValue] == true && prev.keys[key.rawValue] == false) {
return true
}
}
return false
}
func justReleased(keys: KeyCode...) -> Bool {
for key in keys {
if (prev.keys[key.rawValue] == true && curr.keys[key.rawValue] == false) {
return true
}
}
return false
}
func pressed(keys: KeyCode...) -> Bool {
for key in keys {
if (prev.keys[key.rawValue] == true && curr.keys[key.rawValue] == true) {
return true
}
}
return false
}
func update() {
prev = curr
}
}
@figgleforth
Copy link
Author

Can be used like this

class Scene: SKScene {
  override func update(currentTime: NSTimeInterval) {
    super.update(currentTime)

    if (Keyboard.sharedKeyboard.justPressed(KeyCode.Space)) {
      // single key
    } else if (Keyboard.sharedKeyboard.pressed(KeyCode.Space, KeyCode.Return)) {
      // two keys
    } else if (Keyboard.sharedKeyboard.justReleased(KeyCode.Space, KeyCode.W, KeyCode.T, KeyCode.LeftShift)) {
      // many keys
    }
  }

  override func didFinishUpdate() {
    Keyboard.sharedKeyboard.update()
  }

  override func keyUp(theEvent: NSEvent) {
    Keyboard.sharedKeyboard.handleKey(theEvent, isDown: false)
  }

  override func keyDown(theEvent: NSEvent) {
    Keyboard.sharedKeyboard.handleKey(theEvent, isDown: true)
  }
}

of course you can also create an instance of Keyboard.

@vaafoo
Copy link

vaafoo commented Mar 28, 2016

Hi.
First of all let me thank you for this awesome tutorial/sample code. It really helped me out!
I only have one problem: i can't get it to read three or more keypresses. When i have one key pressed down and i press another one it works fine, but when I have two keys pressed down and I press a third one, the third pressed key doesn't register. If you could offer some advice on how to fix this, I shall be forever grateful. Thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment