import SDL2 public class Keyboard { public enum Keys { case a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z case right, left, down, up } public func keyDown(_ key: Keys) -> Bool { _keys[Int(key.sdlScancode.rawValue)] & Self._DOWN == Self._DOWN } public func keyPressed(_ key: Keys, repeat rep: Bool = false) -> Bool { var state = _keys[Int(key.sdlScancode.rawValue)] if rep { state &= ~Self._REPEAT } return state == Self._PRESS } public func keyReleased(_ key: Keys) -> Bool { _keys[Int(key.sdlKeycode.rawValue)] == Self._RELEASE } private static let _UP = UInt8(0b000), _DOWN = UInt8(0b010), _IMPULSE = UInt8(0b001) private static let _REPEAT = UInt8(0b100) private static let _PRESS: UInt8 = _DOWN | _IMPULSE private static let _RELEASE: UInt8 = _UP | _IMPULSE private var _keys = [UInt8](repeating: _UP, count: Int(SDL_NUM_SCANCODES.rawValue)) internal func newTick() { _keys = _keys.map({ $0 & ~(Self._IMPULSE | Self._REPEAT) }) } internal func pressEvent(scan: SDL_Scancode, repeat rep: Bool) { var newState = Self._PRESS if rep { newState |= Self._REPEAT } _keys[Int(scan.rawValue)] = newState } internal func releaseEvent(scan: SDL_Scancode) { _keys[Int(scan.rawValue)] = Self._RELEASE } } extension Keyboard.Keys { internal var sdlKeycode: SDL_KeyCode { switch self { case .a: SDLK_a case .b: SDLK_b case .c: SDLK_c case .d: SDLK_d case .e: SDLK_e case .f: SDLK_f case .g: SDLK_g case .h: SDLK_h case .i: SDLK_i case .j: SDLK_j case .k: SDLK_k case .l: SDLK_l case .m: SDLK_m case .n: SDLK_n case .o: SDLK_o case .p: SDLK_p case .q: SDLK_q case .r: SDLK_r case .s: SDLK_s case .t: SDLK_t case .u: SDLK_u case .v: SDLK_v case .w: SDLK_w case .x: SDLK_x case .y: SDLK_y case .z: SDLK_z case .left: SDLK_LEFT case .right: SDLK_RIGHT case .up: SDLK_UP case .down: SDLK_DOWN } } internal var sdlScancode: SDL_Scancode { switch self { case .a: SDL_SCANCODE_A case .b: SDL_SCANCODE_B case .c: SDL_SCANCODE_C case .d: SDL_SCANCODE_D case .e: SDL_SCANCODE_E case .f: SDL_SCANCODE_F case .g: SDL_SCANCODE_G case .h: SDL_SCANCODE_H case .i: SDL_SCANCODE_I case .j: SDL_SCANCODE_J case .k: SDL_SCANCODE_K case .l: SDL_SCANCODE_L case .m: SDL_SCANCODE_M case .n: SDL_SCANCODE_N case .o: SDL_SCANCODE_O case .p: SDL_SCANCODE_P case .q: SDL_SCANCODE_Q case .r: SDL_SCANCODE_R case .s: SDL_SCANCODE_S case .t: SDL_SCANCODE_T case .u: SDL_SCANCODE_U case .v: SDL_SCANCODE_V case .w: SDL_SCANCODE_W case .x: SDL_SCANCODE_X case .y: SDL_SCANCODE_Y case .z: SDL_SCANCODE_Z case .left: SDL_SCANCODE_LEFT case .right: SDL_SCANCODE_RIGHT case .up: SDL_SCANCODE_UP case .down: SDL_SCANCODE_DOWN } } } extension SDL_KeyCode { internal init(scancode: SDL_Scancode) { self.init(scancode.rawValue | UInt32(SDLK_SCANCODE_MASK)) } }