【问题标题】:Swift Game - Tap and Tap + Hold Gestures?Swift Game - 点击并点击 + 按住手势?
【发布时间】:2015-12-16 14:27:27
【问题描述】:

我正在学习 swift(和 spritekit)并尝试制作一个简单的游戏。

在我的游戏中,英雄应该跳跃或躲避......

点击屏幕时英雄需要跳跃,长按屏幕时需要躲避(long gesture

那么基本的伪代码:

if tapped
    heroJump()
else if tappedAndHeld
    heroDuck()

我有一个func,几乎在所有教程中都可以看到它处理触摸事件:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

for touch in touches {
let location = touch.locationInNode(self) //need location of tap for something

    switch gameState {
        case .Play:
            //do in game stuff

            break
        case .GameOver:
            //opps game ended

            }
            break
    } 
 }
   super.touchesBegan(touches, withEvent: event)
}

有没有办法在这个触摸事件中包含它来决定它是被点击还是被按住?我似乎无法理解这样一个事实,程序总是会在长手势之前识别轻按?!?

无论如何,为了解决我的问题,我发现了THIS 问题,它向我介绍了识别器,我尝试实施:

override func didMoveToView(view: SKView) {
    // other stuff

    //add long press gesture, set to start after 0.2 seconds
    let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
    longPressRecognizer.minimumPressDuration = 0.2
    self.view!.addGestureRecognizer(longPressRecognizer)

    //add tap gesture
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapped:")
    self.view!.addGestureRecognizer(tapGestureRecognizer)
}

这些是手势调用的函数:

func longPressed(sender: UILongPressGestureRecognizer)
{
    if (sender.state == UIGestureRecognizerState.Ended) {
        print("no longer pressing...")
    } else if (sender.state == UIGestureRecognizerState.Began) {
        print("started pressing")
        // heroDuck()
    }
}

func tapped(sender: UITapGestureRecognizer)
{
    print("tapped")
    // heroJump()
}

如何将这两件事结合起来? 我可以添加一种方法来确定它是在我的 touchBegins 事件中被点击还是按住,或者我可以放弃该方法并仅使用上述两个函数吗?

如果使用后者,获取位置的诸多问题之一?

或者也许我完全看错了,在 swift/spritekit 中有一个简单和/或内置的方法?

谢谢。

【问题讨论】:

    标签: swift cocoa-touch sprite-kit uigesturerecognizer


    【解决方案1】:

    您只需要UITapGestureRecognizerUILongPressRecognizer。您无需对touchesBegantouchesEnded 执行任何操作,因为手势识别器会自行分析触摸。

    要获取触摸的位置,您可以在手势识别器上调用locationInView 以获取手势的位置,如果您正在使用多点触控手势并需要每次触摸的位置,则可以调用locationOfTouch。当您需要窗口的基本坐标系中的坐标时,将nil 作为参数传递。

    这是一个工作示例:

    func setupRecognizers() {
         let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
         let longTapRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("handleLongPress:"))
         view.addGestureRecognizer(tapRecognizer)
         view.addGestureRecognizer(longTapRecognizer)
    }
    
    func handleLongPress(recognizer: UIGestureRecognizer) {
        if recognizer.state == .Began {
            print("Duck! (location: \(recognizer.locationInView(nil))")
        }
    }
    
    func handleTap(recognizer: UIGestureRecognizer) {
        print("Jump! (location: \(recognizer.locationInView(nil))")
    }
    

    如果识别出长按handleTap:,则调用。只有当用户抬起手指的速度足够快时,handleTap: 才会被调用。否则 handleLongPress 将被调用。 handleLongPress 只会在长按持续时间过去后被调用。然后handleLongPress 将被调用两次:当持续时间过去时(“开始”)和用户抬起手指后(“结束”)。

    【讨论】:

    • 很好的答案,我现在会调查这个。如何取消 LongPress?例如,如果手势尚未完成(或仍在握持),即使用户仍在握持,如何取消手势?如果这是有道理的......另外,是否可以限制 LongPress 的持续时间,例如,无论用户长按屏幕,LongPress 只持续说 3 秒?感谢您的宝贵时间。
    • 我想我找到了如何取消它,但它似乎很慢:recognizer.cancelsTouchesInView = true
    • 否,该属性决定了手势识别器在识别手势时是否将触摸传递给视图。默认情况下,手势识别器在识别手势时会取消触摸。通过将此属性设置为false,即使手势被识别,视图也会获得触摸。
    • 我不知道你为什么要取消任何东西。该示例的工作方式是,如果用户触摸视图 0.5 秒(长按的默认值),则会触发“鸭子”。在那之后他触摸视图多久都没关系,因为识别器的“结束”状态被忽略了。
    • 哦,我的错。我的游戏状态自引入longPress 后出现故障,所以它崩溃了……我想我需要取消触摸,但实际上是因为如果我躲避,我的gameOver() 方法没有被调用。菜鸟错误无疑。
    【解决方案2】:

    你做和长按一样的事情,等到.Ended事件

    func tapped(sender: UITapGestureRecognizer)
    {
    
        if sender.state == .Ended {
          print("tapped")
        }
    }
    

    点击事件总会发生,这是无法阻止的,因为面对它,你需要触摸屏幕。但是应该发生的是,当您进入长按事件时,点击事件应该进入取消状态而不是结束状态

    【讨论】:

    • 你说得对,触摸总会发生,但手势识别器足够“聪明”,只能调用tappedlongPressed。当触摸足够长时,只会调用longPressed。如果用户在被认为是长按之前抬起手指,则只会调用tapped。永远不要两者兼而有之。
    • 你是对的,点击手势 .Began 状态不再被调用。看起来我可以清理一些旧代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 2016-04-05
    相关资源
    最近更新 更多