检测 Sprite Kit 中的长触摸

Posted

技术标签:

【中文标题】检测 Sprite Kit 中的长触摸【英文标题】:Detect long touch in Sprite Kit 【发布时间】:2015-05-19 23:05:17 【问题描述】:

我在 SKScene 中有一个节点,我正在根据用户的触摸移动它。基本上,这个角色也应该试图跟随用户的手指(假设手指在屏幕上)。我目前已经这样实现了,效果很好:

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
    let touch = touches.first as! UITouch
    player.runAction(SKAction.moveTo(touch.locationInNode(self), duration: 1))


override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) 
    let touch = touches.first as! UITouch
    player.runAction(SKAction.moveTo(touch.locationInNode(self), duration: 1))


override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) 
    player.removeAllActions()


override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) 
    player.removeAllActions()

但是,问题在于,如果用户将手指放在手机上。 touchesBegan 只被调用一次,那是点击开始的时候,而不是被按住的时候。我希望玩家角色不断尝试触及手指。

我将相机置于节点的中心,因此节点应该触摸手指的唯一时间是用户将手指放在节点上/在节点中(即与节点相同的位置)。因此,在我运行 SKAction 移动节点后,触摸无效,因为它位于旧位置。

我该怎么做?

【问题讨论】:

【参考方案1】:

你可以像这样注册一个长触摸事件:

let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
self.view.addGestureRecognizer(longPressRecognizer)

func longPressed(sender: UILongPressGestureRecognizer) 
    // your code

【讨论】:

我认为这也可以,但是我遇到了和以前一样的问题。手势调用的动作函数只在每次手指移动时调用一次。由于我将节点居中并将其移动到触摸位置,因此触摸当前位置会发生变化。所以由于这个节点将停止跟随手指,因为它认为它已经到达手指位置,而实际上手指位置由于节点的移动而刚刚改变。 我正在寻找的一个好主意是 Apples SpriteKit 示例冒险游戏中的运动是如何工作的。我打算今晚晚些时候看看。【参考方案2】:

对于 Swift 4:

您首先要使 GameScene 成为 UIGestureRecognizerDelegate

class GameScene: SKScene, UIGestureRecognizerDelegate 

因此您还需要将委托方法添加到 GameScene 类:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool         
        return true

然后在 GameSceneoverride func didMove(to view: SKView) 中添加以下内容:

let pressed:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPress(sender:)))
pressed.delegate = self
pressed.minimumPressDuration = 0.1
view.addGestureRecognizer(pressed)

最后在 GameScene 中添加处理长按的函数(您也可以在其中识别长按的状态):

func longPress(sender: UILongPressGestureRecognizer) 

     if sender.state == .began  print("LongPress BEGAN detected")             
     if sender.state == .ended  print("LongPress ENDED detected") 


【讨论】:

【参考方案3】:

将两个实例变量添加到您的 SKScene,BOOL fingerIsTouchingCGPoint touchLocation

-touchesBegan: 内部,将fingerIsTouching 设置为YES,并将touchLocation 更新到正确的位置。 在您的 SKScene 的 -update: 方法中,检查 fingerIsTouching 是否为 YES 并根据 touchLocation 移动您的角色。我推荐使用-update:,因为它每帧调用一次,这就足够了。不过,您可能必须使用其他方法来移动角色,而不是 SKAction

不要忘记在-touchesMoved: 中更新touchLocation,并在-touchesCancelled:-touchesEnded: 中重置fingerIsTouching :)

对不起 Obj-C,希望这能说明问题。

【讨论】:

这就是我最终要做的,虽然比我想要的要多一些工作,但效果很好。

以上是关于检测 Sprite Kit 中的长触摸的主要内容,如果未能解决你的问题,请参考以下文章

SKView bounds.size 在触摸事件时反转(Sprite Kit)

Sprite Kit 只允许一键式

我们如何检测精灵的触摸?

在Sprite纹理中检测触摸而不是整个框架iOS Swift SpriteKit?

无法在触摸上添加 Sprite - Cocos2d-x

Swift Sprite Kit 相机运动