How can Mac OS X games receive low-level keyboard input events?

≯℡__Kan透↙ 提交于 2019-11-28 17:33:23

I have had good luck with #3, but it requires a lot of heavy lifting if you want to support anything beyond the keyboard.

One quick point before we dive in though, Carbon and IOKit HID are two separate thing. Carbon may go away at some point. But IOKit HID is here to stay and just got a nice facelift in 10.5.

For a full example of how this stuff all fits together, take a look at https://github.com/OpenEmu/OpenEmu/blob/master/OpenEmu/OEHIDManager.m. That is a small piece of the puzzle as there are other files in there as well.

The documentation for what you're wanting to do can be found http://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html

Again, this is not going to disappear anytime soon and is completely separate from Carbon and Carbon Events.

I'm late to this party, but here's my solution for an OSX game I'm writing using Swift. It's very simple, and seems to be working pretty well.

First you can put this code in the controller which is receiving keyboard events:

var keysDown = Set<UInt16>()

override func keyDown(e: NSEvent) {
    keysDown.insert(e.keyCode)
}

override func keyUp(e: NSEvent) {
    keysDown.remove(e.keyCode)
}

Then, other parts of the system can determine if a particular key is down:

if (keysDown.contains(49)) {
    // space bar is down
}

Or loop through all the keys which are currently pressed

for char in keysDown {

    switch char {

    case 49:
        // space
        player.jump()
    case 126:
        // up
        player.moveForward()
    case 124:
        // right
        player.turnRight()

        //   ... etc ...

    default:
        // during development I have this line so I can easily see which keys have which codes
        print(char)
    }
}

Note keysDown is a Swift Set, so you don't have to worry about duplicates or ordering. A key is either in the set or it isn't.

I'm not too sure how standardised the keycodes are. But you could offer a keyboard configuration page where the user can type keys for each action, and then save whatever keycode this happened to be.

Ok so I'm really late to the party but I think mine is just straight to the point and resembles Mr. Howards solution above. Keep in mind this input is being used to control the camera in a SpriteKit game. This way you get smooth continuous movement and precise stopping.

let moveRight: SKAction = SKAction.repeatForever(SKAction.moveBy(x: -5000, y: 0, duration: 1.5))
...

override func keyDown(with event: NSEvent) {
    camera!.constraints = [] // remove constraints usually added by a cameraComponent.

    let ekc = event.keyCode
    if ekc == 123 { camera!.run(moveLeft, withKey: "moveLeft") }
    if ekc == 124 { camera!.run(moveRight, withKey: "moveRight") }
    if ekc == 126 { camera!.run(moveUp, withKey: "moveUp") }
    if ekc == 125 { camera!.run(moveDown, withKey: "moveDown") }

    print("keyDown: \(event.characters!) keyCode: \(event.keyCode)")
}


override func keyUp(with event: NSEvent) {
    let ekc = event.keyCode
    if ekc == 123 { camera!.removeAction(forKey: "moveLeft") }
    if ekc == 124 { camera!.removeAction(forKey: "moveRight") }
    if ekc == 126 { camera!.removeAction(forKey: "moveUp") }
    if ekc == 125 { camera!.removeAction(forKey: "moveDown") }
}

Have a look at ControllerMate and manymouse.

http://icculus.org/manymouse/

http://www.orderedbytes.com/controllermate/

There are also some Device Classes in polkit (Obj-C toolkit) including ...

  • HIDController to use USB HID devices
  • AppleRemote to use the Apple Remote
  • MidiController to use Midi devices
  • OSCController to use OSC compatible devices over UDP
  • SerialPort to use any serial port device
  • SC2004LCDModule to use the SC 2004 from siliconcraft.net

http://code.google.com/p/polkit/

I found a very good example of using Quartz Event Taps.

however the problems are:

  1. for certain event types, the user needs to run the application in root privilege. for example intercepting keydown and keyup events requires root.

  2. the interception is system wide, which means when the program runs, it will capture all key events even those sent to other applications. implementation needs to be very careful in order to not to break other applications.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!