touchesBegan против UITapGestureRecognizer

Итак, я делаю игру spritekit, используя Swift. И мне было интересно, что лучше всего использовать жестами?

В настоящее время у меня есть override func touchesBegan, обрабатывающий все нажатия, и UILongPressGestureRecognizer, обрабатывающий длинные нажатия/удержания.

Итак, вы знаете, тап нажимает кнопки и герой прыгает. Долгая задержка заставляет героя пригнуться.

По какой-то причине моя функция longPress не всегда вызывается (иногда вы можете нажать и удерживать 10 раз, а затем она перестает вызываться (не распознается), в других случаях это 5, это меняется), и это привело к тому, что вчера целый день пробовать новые вещи и исследовать, что привело меня к этому вопросу.

Лучше использовать touchesBegan или переместить все мои сенсорные вызовы в новую функцию, обрабатываемую UITapGestureRecognizer?

Я переместил все с touchesBegan на UITapGestureRecognizer, но это кажется очень вялым. Но, может быть, я неправильно это реализовал?

Вот как настроены recognisers:

func setupRecognizers() {
    let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    view!.addGestureRecognizer(tapRecognizer)

    let longTapRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("handleLongPress:"))
    longTapRecognizer.minimumPressDuration = 0.2
    view!.addGestureRecognizer(longTapRecognizer)

}

Это функции, которые обрабатывают жесты:

func handleTap(recognizer: UIGestureRecognizer) {
    //currently all handled in touchesBegan
}

func handleLongPress(recognizer: UIGestureRecognizer) {
    print("1 --------> longPress Called.... ", recognizer.state.rawValue, gameState)
    if gameState == .Play {
       //do stuff
       //duck Hero
    } else {
       //switch gameState
    }
}

Это функция, которая обрабатывает касания/нажатия:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

for touch in touches {
     let location = touch.locationInNode(self)

     //do stuff

     switch gameState {
        case .MainMenu:
        break
        ... //more states
        }
   }
   super.touchesBegan(touches, withEvent: event)
}

Если я перемещаю все из touchesBegans в tapRecogniser (пустая функция выше), мне нужно реализовать и это, чтобы преобразовать координаты местоположения касания:

func handleTap(recognizer: UIGestureRecognizer) {
    let location = convertPointFromView(CGPoint(x: recognizer.locationInView(nil).x, y: recognizer.locationInView(nil).y))
    print("Converted Coords: ", location)

    //then do all touchesBegan stuff
 }

Я пробовал оба, но последний кажется очень медленным и вялым. Может быть, я забыл реализовать что-то, что рекомендуется?

Кажется, мой жест longPress не всегда вызывается, может ли быть какой-то конфликт между ними?


person Reanimation    schedule 17.12.2015    source источник
comment
я бы не стал использовать что-либо, связанное с UIKit, в игре со спрайткитом. если вы хотите проверить, как долго прикосновение, просто время, используя ваш метод обновления. постарайтесь использовать в своей игре как можно больше инструментов spritekit. Все, что связано с UIKit (игровое меню или элементы управления), я бы поместил внутрь UIViewController.   -  person hamobi    schedule 17.12.2015
comment
Все, включая меню, создается в gameScene и различается по игровым состояниям (inGame, Menu, gameOver) и т. д. Итак, вы рекомендуете таймер в touchesBegan и if timer > longPressValue duck, else jump? Или у SpriteKit разные жесты тапа?   -  person Reanimation    schedule 17.12.2015
comment
у него нет тап-жестов... вам просто нужно зафиксировать время, когда вы держите палец, и сбросить таймер, когда вы отпустите. такая штука.   -  person hamobi    schedule 17.12.2015
comment
Я дам это назад, это может решить, почему longPress не всегда вызывается и сохраняет все внутри touchesBegan ... может работать лучше.   -  person Reanimation    schedule 17.12.2015
comment
обязательно дайте мне знать, если вам нужно, чтобы я написал код   -  person hamobi    schedule 17.12.2015
comment
@hamobi, если вы хотите написать пример в ответе ниже, это было бы действительно здорово. Я уверен, что ваш инструмент будет более эффективным, чем мой :) Спасибо.   -  person Reanimation    schedule 17.12.2015


Ответы (1)


поэтому, если вы удержите красный квадрат в течение двух секунд, вы получите сообщение, когда вы отпустите, сообщение исчезнет. возможно, вам придется добавить туда несколько логических значений, чтобы убедиться, что ваш персонаж не повторяет какое-либо действие каждый кадр после 2-секундного удержания кнопки. этого должно быть достаточно, чтобы вы начали, надеюсь

import SpriteKit

class GameScene: SKScene {

    // time values
    var delta = NSTimeInterval(0)
    var last_update_time = NSTimeInterval(0)

    var longTouchTimer = NSTimeInterval(0)
    var touched = false
    var testLabel = SKLabelNode(text: "you have touched for awhile now bro")

    let touchSprite = SKSpriteNode(color: SKColor.redColor(), size: CGSizeMake(100, 100))

    override func didMoveToView(view: SKView) {
        touchSprite.position = CGPointMake(self.size.width/2, self.size.height/2)
        addChild(touchSprite)

        testLabel.hidden = true
        testLabel.position = touchSprite.position
        testLabel.position.y += 100
        testLabel.fontSize = 20
        addChild(testLabel)
    }


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if touchSprite.containsPoint(location) {
                touched = true
            }
        }
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if !touchSprite.containsPoint(location) {
                touched = false
                longTouchTimer = 0
            }
        }
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touched = false
        longTouchTimer = 0
    }

    override func update(currentTime: NSTimeInterval) {
        if last_update_time == 0.0 {
            delta = 0
        } else {
            delta = currentTime - last_update_time
        }

        last_update_time = currentTime

        if touched {
            longTouchTimer += delta
        }

        if longTouchTimer >= 2 {
            testLabel.hidden = false
        } else {
            testLabel.hidden = true
        }
    }
}
person hamobi    schedule 17.12.2015
comment
О, круто. Спасибо. Я попробую сейчас. Спасибо за публикацию. - person Reanimation; 18.12.2015
comment
@hamobi отличная статья. Простое использование методов касания для запуска и остановки таймеров (NSTimeIntervals, а не NSTimer, который не следует использовать в SpriteKit) при использовании обновлений currentTime идеально. Обратите внимание: поскольку вы используете текущее время вместо системного времени, оно отлично работает, когда игра по какой-либо причине приостановлена. - person Skyler Lauren; 18.12.2015
comment
У меня просто пустой экран.. может быть, я делаю что-то глупое :S - person Reanimation; 18.12.2015
comment
Возможно, это связано с тем, как настроен ваш конкретный проект. В конечном счете, важно использовать обновление для увеличения вашей временной переменной. Просто попробуйте добавить эту часть в свой проект - person hamobi; 18.12.2015
comment
Получил это работает, думаю, что мой проект был странным. Удалил его, запустил снова и работает нормально... Есть ли способ заставить longTouchTimer работать внутри touchesBegan? Потому что, как вы сказали, если я просто прыгну () или пригнусь () в обновлении, он будет вызываться каждый кадр. - person Reanimation; 18.12.2015
comment
Вам просто нужно добавить логическое значение для прыжка или приседания, чтобы проверить, прыгаете ли вы уже или пригибаетесь. - person hamobi; 18.12.2015
comment
@hamobi просто чтобы вы знали, кажется, у меня наконец-то все работает, и это действительно гладко, буквально лучше, чем касания длинными жестами. Так что большое спасибо! :D - person Reanimation; 18.12.2015