C. Greene
C. Greene

Reputation: 281

mac Swift multiple keyDown events

I am in the process of creating a 2D tile-based platform game for Mac OSX in swift. I have come across problems with the controls when more than one key is pushed at a time. For example; if 'D' makes the character move to the right, and 'W' makes him jump; if I hold 'D' to make the character run, then tap 'W' to make him jump, he will stop once he lands. The only way for him to continue to move to the right is to retouch 'D' again, which is certainly undesirable. It appears as though when the 'W' key is pressed, it cancels the 'D' keyDown event. If anyone has any suggestions on how I can make it so that multiple keys can be pressed without canceling other similar events I sure would appreciate it. This is how my KeyDown events looks:

 func returnChar(theEvent: NSEvent!) -> Character?{
        let s: String = theEvent.characters!
        for char in s {
            return char}
        return nil
}

override func keyDown(theEvent: NSEvent) {
                let s: String = String(self.returnChar(theEvent)!)
                switch(s){
    case "w":
        player.jump()
    case "s":
        // nothing yet
    case "d":
        player.moveLeftOrRight(CGVector(dx: 1.0, dy: 0.0))
    case "a":
        player.moveLeftOrRight(CGVector(dx: -1.0, dy: 0.0))



    default:
            println("default")
        }
}

Upvotes: 2

Views: 1706

Answers (2)

kernelpanic
kernelpanic

Reputation: 530

Jim Garrison's answer seems correct. A workaround in this case, could be to have the character move right when you press the D key down, and continue to move right using a loop until the D key is released, which you can check using the func keyUp(theEvent: NSEvent)

If using SpritKit, you can do the character movement in the update method while using a bool that is set in the keyDown and keyUp method.

Upvotes: 0

Jim Garrison
Jim Garrison

Reputation: 86754

The repeated keydown events that occur when a key is held down are generated by the keyboard hardware. On the PC, the protocol definition says:

If you press a key, its make code is sent to the computer. When you press and hold down a key, that key becomes typematic, which means the keyboard will keep sending that key's make code until the key is released or another key is pressed. To verify this, open a text editor and hold down the "A" key. ... Typematic data is not buffered within the keyboard. In the case where more than one key is held down, only the last key pressed becomes typematic. Typematic repeat then stops when that key is released, even though other keys may be held down.

Since both PCs and Macs can use the same USB keyboards (modulo some key remapping), I'm pretty sure they both use the same protocol.

In the case you describe, the problem occurs because even though you're holding down D, when you hit W, the keyboard stops repeating the D key. The sequence of events is:

Keydown D
Keydown D
...
Keydown W
Keyup   W

and at this point the keyboard events stop. Notice that the Keyup D has not occurred, so you actually know that the D key is still down, but now it is up to you to simulate the repeated keypresses.

I suggest you research how to disable autorepeat altogether in the keyboard hardware (or just ignore the key repeat events) and generate the desired game behavior yourself. You could easily do this by tracking the state of each key using Keydown and Keyup events, ignoring repeated Keydown.

Upvotes: 4

Related Questions