为什么被触摸的 SKSpriteNode 在被快速拖离和进入游戏视图后停止移动?

Why has the touched SKSpriteNode stopped moving after being quickly dragged off and on game view?

我已经在我的游戏中实现了 SKSpriteNodes 的多点触控拖动。

它正在运行,但是当然有一个错误。

在 iOS 模拟器中, 情况 1:如果我在可视屏幕周围拖动一个节点,然后继续将节点拖离可视屏幕,它会消失,然后继续将节点拖回到屏幕上,它会正常显示。这很好。只有慢慢来才有效。

案例 2:如果我做完全相同的动作(如案例 1 中所述),除了这次我做的非常快,当节点重新出现在屏幕上时,它会 "stick" 到一个点屏幕。此时我还没有结束触摸,即鼠标按钮仍然被按住。在模拟器上看起来我什么也没拖。

预期的行为是触摸开始后,在触摸位置创建节点(工作正常),拖动节点(工作)然后如果节点被拖出屏幕,触摸应该结束,并且应删除该节点。

正在字典数组中跟踪节点和触摸。

在屏幕截图中,我单击一次,节点出现,一直按住并开始多次快速将其拖到屏幕左侧。它创建了许多本应消失的节点。如果我慢慢地拖出屏幕然后再拖回到屏幕上,它不会产生 "extra" 个节点。

我已经在 GitHub 上放置了我的代码的简化版本,供您自己尝试这个问题。我在这个问题上花了大约 10 个小时,但没有找到解决方案。非常感谢您的帮助。 GitHub repository Whosebug Game1 project

var selectedNodes:[UITouch:SKSpriteNode] = [UITouch:SKSpriteNode]()

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

    for touch:AnyObject in touches{
        var location = touch.locationInNode(self)

        // Add in the node            
        var hero = SKSpriteNode(imageNamed: "Player")
        hero.name = "player"

        // Make sure it is not off of the screen.
        hero.position = location
        self.addChild(hero)

        let touchObj = touch as UITouch
        selectedNodes[touchObj] = hero

    }
}

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {

    for touch:AnyObject in touches {
        //println("touhex count \(touches.count)")
        let location = touch.locationInNode(self)
        let touchObj = touch as UITouch

        //println("Touches moved current loc:  \(location)")

        // Update the position of the sprites
        if let node:SKSpriteNode? = selectedNodes[touchObj] {
            if (node?.name == "player" || node?.name == "bar")
            {
                let size:CGFloat = CGFloat(node!.size.width)/2
                node?.position = location

            }
        }

    }

}

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {

    for touch:AnyObject in touches {
        let touchObj = touch as UITouch
        let location = touch.locationInNode(self)

        println("Touch Ended \(location)")

        if let exists:AnyObject? = selectedNodes[touchObj] {
            println("attempt to remove")
            let node:SKSpriteNode? = self.nodeAtPoint(location) as? SKSpriteNode
            println("ended touch locaiton \(location)")
            println("ended npde position \(node?.position)")

            for (node) in selectedNodes{
                println("Touch n1 \(node.1.position)")
            }

            if (node?.name == "player")
            {
                println("removed")
                node?.removeFromParent()
                selectedNodes[touchObj] = nil
            }
        }            
    }                
}

问题是当你快速移动它时,touchesEnded 函数可能会在没有更新位置的情况下触发。
在您的 touchesEnded 函数中,不要使用 nodeAtPoint,只需使用 exists.removeFromParent()

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {

    for touch:AnyObject in touches {
        let touchObj = touch as UITouch

        if let exists:SKNode = selectedNodes[touchObj] {

            if (exists.name == "player")
            {
                exists.removeFromParent()
                selectedNodes[touchObj] = nil
            }
        }            
    }                
}