3

In Xcode does sprite-kit have any type of built in arrow key support? I am currently using the regular swift key codes and there is a delay when the key is held. This makes it hard for my game controls.

this is how I am currently reading the arrow keys.

override func keyDown(with event: NSEvent) {

    let keycode = event.keyCode

    if(keycode == 125)//up

    {
        player.position.y -= 10
    }

    else if(keycode == 126)//down

    {
        player.position.y += 10
    }

    if(keycode == 124)//right

    {
        player.position.x += 10
    }

    else if(keycode == 123)//left

    {
        player.position.x -= 10

    }

I know this is a stupid question but I an new to swift and I can't find any other answers to this question.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Big Papa
  • 77
  • 1
  • 7

1 Answers1

5

You're not supposed to abuse keyboard repeat in order to run code repeatedly when a key is held. Instead, keep track yourself of which keys are pressed yourself using keyDown and keyUp.

The easiest way to do this is with instance variables:

var leftPressed = false
var rightPressed = false
var upPressed = false
var downPressed = false

You can also use an enum, an array of key codes, or whatever works best for your app.

In keyDown and keyUp, set or clear the key pressed flags. You can make these functions much more concise using a switch/case, and if you import Carbon.HIToolbox, you'll have some constants available for the virtual key codes:

override func keyDown(with event: NSEvent) {
    switch Int(event.keyCode) {
    case kVK_LeftArrow:
        leftPressed = true
    case kVK_RightArrow:
        rightPressed = true
    case kVK_UpArrow:
        upPressed = true
    case kVK_DownArrow:
        downPressed = true
    default:
        break
    }
}

override func keyUp(with event: NSEvent) {
    switch Int(event.keyCode) {
    case kVK_LeftArrow:
        leftPressed = false
    case kVK_RightArrow:
        rightPressed = false
    case kVK_UpArrow:
        upPressed = false
    case kVK_DownArrow:
        downPressed = false
    default:
        break
    }
}

Then, update the player's position in your update method:

var lastUpdate: TimeInterval!
func update(currentTime: TimeInterval) {
    defer { lastUpdate = currentTime }
    guard lastUpdate != nil else {
        return
    }

    let dt = currentTime - lastUpdate
    guard dt < 1 else {
        return //so nothing "jumps" when the the game is unpaused
    }


    if leftPressed {
        player.position.x -= 10 * dt
    }
    if rightPressed {
        player.position.x += 10 * dt
    }
    if upPressed {
        player.position.y -= 10 * dt
    }
    if downPressed {
        player.position.y += 10 * dt
    }
}
NobodyNada
  • 7,529
  • 6
  • 44
  • 51