2015-12-21 4 views
2

Я пишу игру в Spritekit для OSX. Как проверить, нажата ли клавиша? Рассмотрим этот пример:Как определить, нажата ли клавиша на OS X?

//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.

Я думаю, что мне, возможно, придется поддерживать Array из булевых, по одному для каждого кода и обновлять его содержимое, когда получаю события keyDown и keyUp. Но я надеялся на более элегантное решение, поскольку это кажется довольно тривиальной функциональностью.

ответ

3

Попробуйте так:

Как я уже говорил, вам нужно добавить addLocalMonitorForEventsMatchingMask к вашему игровому методу сцены didMoveToView для событий KeyUp и KeyDown и добавить переключатель заявление в случае KEYCODE:

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

Если это более удобно для опроса вместо приема уведомлений, вы можете использовать функцию Quartz Event Services CGEventSourceKeyState.

0

Я знаю, что это старо, но проблема довольно общая, а другие ответы на самом деле не решают проблему в том, как задавался вопрос, т. Е. Спрашивая систему для состояния клавиатуры, а не для изменения Мероприятия.

SFML уже решил эту проблему. Проверьте the code, в частности класс HIDInputManager. Кстати, я нашел документацию Apple о IOKit бесполезной, как она есть.

При написании игры, позвольте мне рекомендовать полагаться на SFML или аналогичную инфраструктуру вместо того, чтобы решать эту и другие проблемы низкого уровня самостоятельно. Кроме того, вы получаете бесплатное межплатформенное решение.

Смежные вопросы