【问题标题】:How to detect if a key is pressed on OS X?如何检测是否在 OS X 上按下了某个键?
【发布时间】:2016-03-27 07:05:23
【问题描述】:

我正在用 Spritekit 为 OSX 编写游戏。如何检查当前是否正在按下某个键?考虑这个例子:

//some code. this could be e.g. inside a game loop

if (/*is key 'w' pressed*/) {
    // move forward
}

//some more code

Swift 和 Objective-C 解决方案都很有用。

注意:我对接收或处理该事件不感兴趣,因此我希望尽可能避免这种情况。我只需要检查当前是否按下了特定的键。

注意#2:这个问题不是链接问题的重复,因为它仅从接收“keyPressed”事件的角度解决问题(作为方法调用的参数) ,而不是从在别处执行检查以找出当前是否正在按下某个键的角度。换句话说,它并不能帮助我填写上面 if 语句中的条件。

我想我最终可能不得不维护一个布尔数组,每个键码一个,并在收到 keyDown 和 keyUp 事件时更新其内容。但我希望有一个更优雅的解决方案,因为这似乎是非常微不足道的功能。

【问题讨论】:

    标签: objective-c swift macos sprite-kit keyboard


    【解决方案1】:

    如果轮询而不是接收通知更方便,您可以使用 Quartz 事件服务功能CGEventSourceKeyState

    【讨论】:

      【解决方案2】:

      试试这样:

      正如我已经提到的,您需要将 addLocalMonitorForEventsMatchingMask 添加到您的游戏场景方法 didMoveToView 中,用于 keyUp 和 keyDown 事件,并在 keyCode 事件中添加 switch 语句:

      import SpriteKit
      
      class GameScene: SKScene {
      
          let sprite = SKSpriteNode(imageNamed:"Spaceship")
      
          var keyDownState:[String:Bool] = ["k":false, "j":false]
          var movingLeft  = false
          var movingRight = false
      
          override func didMoveToView(view: SKView) {
      
              sprite.position = CGPoint(x: view.scene!.frame.midX, y: view.scene!.frame.midY)
              sprite.setScale(0.5)
              addChild(sprite)
      
              NSEvent.addLocalMonitorForEventsMatchingMask(.KeyDownMask) { (theEvent) -> NSEvent! in
                  print("keyDown event")
                  switch theEvent.keyCode {
                  case 38:
                      print("j is down")
                      self.keyDownState["j"] = true
                  case 40:
                      print("k is down")
                      self.keyDownState["k"] = true
                  default:
                      print("unknown key")
                  }
                  print(self.keyDownState.description)
                  // j and k are pressed
                  if self.keyDownState["j"]! && self.keyDownState["k"]! {
                      self.sprite.removeAllActions()
                      view.scene?.backgroundColor = NSColor.init(red: 1, green: 1, blue: 0, alpha: 1)
                  }
                  // j is pressed
                  if self.keyDownState["j"]! && !self.keyDownState["k"]! {
                      view.scene?.backgroundColor = NSColor.greenColor()
                      if !self.movingLeft {
                          self.sprite.removeActionForKey("moveSpriteRight")
                          self.movingRight = false
                          let moveSpriteLeft = SKAction.moveByX(-50, y: 0, duration: 0.1)
                          self.sprite.runAction(SKAction.repeatActionForever(moveSpriteLeft) , withKey: "moveSpriteLeft")
                          self.movingLeft = true
                      }
                  }
                  // k is pressed
                  if !self.keyDownState["j"]! && self.keyDownState["k"]! {
                      view.scene?.backgroundColor = NSColor.redColor()
                      if !self.movingRight {
                          self.sprite.removeActionForKey("moveSpriteLeft")
                          self.movingLeft = false
                          let moveSpriteRight = SKAction.moveByX(50, y: 0, duration: 0.1)
                          self.sprite.runAction(SKAction.repeatActionForever(moveSpriteRight) , withKey: "moveSpriteRight")
                          self.movingRight = true
                      }
                  }
                  return theEvent
              }
      
              NSEvent.addLocalMonitorForEventsMatchingMask(.KeyUpMask) { (theEvent) -> NSEvent! in
                  print("keyUp event \(theEvent.keyCode)")
                  switch theEvent.keyCode {
                  case 38:
                      print("j is up")
                      self.keyDownState["j"] = false
                      self.movingLeft = false
                  case 40:
                      print("k is up")
                      self.keyDownState["k"] = false
                      self.movingRight = false
      
                  default:
                      print("unknown key")
                  }
                  print(self.keyDownState.description)
                  if self.keyDownState["j"]! && !self.keyDownState["k"]! {
                      view.scene?.backgroundColor = NSColor.greenColor()
                          self.sprite.removeActionForKey("moveSpriteRight")
                          self.movingRight = false
                          let moveSpriteLeft = SKAction.moveByX(-50, y: 0, duration: 0.1)
                          self.sprite.runAction(SKAction.repeatActionForever(moveSpriteLeft) , withKey: "moveSpriteLeft")
                          self.movingLeft = true
      
                  }
                  if !self.keyDownState["j"]! && self.keyDownState["k"]! {
                      view.scene?.backgroundColor = NSColor.redColor()
                          self.sprite.removeActionForKey("moveSpriteLeft")
                          self.movingLeft = false
                          let moveSpriteRight = SKAction.moveByX(50, y: 0, duration: 0.1)
                          self.sprite.runAction(SKAction.repeatActionForever(moveSpriteRight) , withKey: "moveSpriteRight")
                          self.movingRight = true
                  }
                  if !self.keyDownState["j"]! && !self.keyDownState["k"]! {
                      self.sprite.removeAllActions()
                      view.scene?.backgroundColor = NSColor(red: 0.72628, green: 0.726298 , blue: 0.726288, alpha: 1)
                  }
                  return theEvent
              }
          }
      
          override func mouseDown(theEvent: NSEvent) {
              /* Called when a mouse click occurs */
      
          }
      
          override func update(currentTime: CFTimeInterval) {
              /* Called before each frame is rendered */
          }
      }
      

      Sample project

      【讨论】:

        【解决方案3】:

        我知道这是旧的,但问题很笼统,其他答案并没有真正解决问题所要求的问题,即通过询问系统键盘状态,而不是更改事件.

        SFML 已经解决了这个问题。检查the code,特别是HIDInputManager 类。顺便说一句,我发现 Apple 的 IOKit 文档毫无帮助。

        在编写游戏时,我建议您使用 SFML 或类似的框架,而不是自己解决这个问题和其他低级问题。此外,这样您就可以免费获得跨平台解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-03
          • 1970-01-01
          • 2017-05-26
          • 2014-07-13
          • 1970-01-01
          • 2014-04-05
          • 2011-06-22
          相关资源
          最近更新 更多