58986


[spritekitを用いたMac向けのアプリでキーボードの同時入力を処理したい](https://ja.stackoverflow.com/questions/57748/spritekit%E3%82%92%E7%94%A8%E3%81%84%E3%81%9Fmac%E5%90%91%E3%81%91%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AA%E3%81%A7%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AE%E5%90%8C%E6%99%82%E5%85%A5%E5%8A%9B%E3%82%92%E5%87%A6%E7%90%86%E3%81%97%E3%81%9F%E3%81%84)

こちらの質問に関係する話になりますので、ご参照ください。

一度は解決した問題でしたが、ここで困ったことが起こりました。  
これでは確かに数値を単純にいじるだけであれば問題ないのですが、WASD移動に加えて左シフトのホールドによるスニーク（低速移動）を実装しようとした時に動作しないことは自明です。

どのようにすれば２つ以上のキーが押されている状態であるかを取得することができるのでしょうか


CC BY-SA 4.0
2019-09-10T08:31:43.510
57964
2019-09-11T12:11:58.883
16877
question
swift4 spritekit
SpriteKitにおいてキーボード入力を同時に２つ以上受け付ける方法を知りたい


macOS 10.12 以降のみサポートで良いなら`keyDown(with: theEvent)`と`keyUp(with:
theEvent)`を以下のように修正することで可能かと思います。

  * `shift`で減速、`control`で加速を想定しています
  * 同時押しによる衝突を避けるため、`shift`が押されていないときのみ`control`が押されているか？の判断をしています

[code]

    private let DefaultSpeed: Int = 10
    private let SpeedUpRate: Float = 2.0
    private let SlowDownRate: Float = 0.5
    
    override func keyDown (with event: NSEvent) {
        let accelarateRate: Float = checkAccelarateRate(for: event)
    
        switch event.keyCode {
        case 13:
            distanceX = DefaultSpeed * accelerateRate
        case 1:
            distanceX = -DefaultSpeed * accelerateRate
        case 0:
            distanceY = -DefaultSpeed * accelerateRate
        case 2:
            distanceY = DefaultSpeed * accelerateRate
        default:
            break
        }
    }
    
    override func keyUp (with event: NSEvent) {
        let accelarateRate: Float = checkAccelarateRate(for: event)
        if accelerateRate != 1.0 {
            distanceX = distanceX / accelerateRate
            distanceY = distanceY / accelerateRate
        }
    
        switch event.keyCode {
        case 13, 1:
            distanceX = 0
        case 0, 2:
            distanceY = 0
        default:
            break
        }
    }
    
    private func checkAccelarateRate (for event: NSEvent) -> Float {
        var accelerateRate: Float = 1.0
        let modifiers: NSEvent.ModifierFlags = event. modifierFlags
        if modifiers.contains(NSEvent.ModifierFlags.shift) {
            accelerateRate = SlowDownRate
        } else if modifiers.contains(NSEvent.ModifierFlags.control) {
            accelerateRate = SpeedUpRate
        }
    
        return accelerateRate
    }
    
    
[/code]

重複の修正漏れを予防するために、同じ意味で同じことを書いている部分の定数化、関数化を行いました。


CC BY-SA 4.0
2019-09-11T07:25:29.140
58986
2019-09-11T12:11:58.883
2019-09-11T12:11:58.883
14745
14745
57964
answer