如何检测节点

时间:2017-11-20 19:24:17

标签: swift sprite-kit uitouch touchesbegan

我有一个应用程序,每隔1秒在屏幕上产生一个球。现在,我希望用户触摸那些使它们消失的球(removeFromParent())。据我所知,我必须通过touchesBegan设置触摸功能,我这样做,这是我的代码:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches{
        let positionOfTouch = touch.location(in: self)
        enumerateChildNodes(withName: "BALL") { (node: SKNode, nil) in
            if positionOfTouch == node.position {
                print("just touched the ball")
            }
            else{
                print("error")
            }
        }
    }

问题是,当我触摸屏幕/球时控制台打印错误而不是只是触球,这意味着我的代码不起作用。此外,控制台将错误消息打印为我视图中的球数。我不知道我做错了什么,以及如何真正设置这个功能。 这是我的createBall函数,它从我的BallNode类(类型SKShapeNode)实现:

    func createBall(){
    let ball = BallNode(radius: 65)
    print(ball.Name)
    print(ball._subName!)

    ball.position.y = ((frame.size.height) - 200)
    let ballXPosition = arc4random_uniform(UInt32(frame.size.width)) // set the ball a randon position from the top of the screen
    ball.position.x = CGFloat(ballXPosition)

    ball.physicsBody?.categoryBitMask = PhysicsCategory.ball // ball's category bitMask
    ball.physicsBody?.collisionBitMask = PhysicsCategory.ball // prevent objects from intersecting
    ball.physicsBody?.contactTestBitMask = PhysicsCategory.topBorder // when need to know if two objects touch each other

    addChild(ball)

}
你可以帮帮我吗?因为我快速退出了swift,我也希望得到一些关于这种触摸检测的解释(和一般的接触 - 苹果文档很差)。

3 个答案:

答案 0 :(得分:2)

每次触摸屏幕时,您都会在所有球中骑自行车,看看您是否正在触摸其中一个。如果你在屏幕上有50个球,它会通过它们看看你是否正在接触1.这不是一个有效的方法来确定你是否正在接触1。

有很多方法可以做到这一点,但我要做的是处理Ball类内部的触摸。这样你就不必弄清楚你是否正在接触一个球以及它可能是一个球。

  

协议的解释(尽我所能)现在看起来似乎有点多了,但你学习和理解的协议越快,你就越好(IMO)。

     

在这个例子中,我们将使用一个协议来设置一个委托   BallNode类。协议是一组用户定义的规则&#34;那一定是   然后是您指定符合该协议的任何类。   在我的例子中,我声明一个类要符合   BallNodeDelegate协议它必须包含didClick func。当你   在GameScene之后添加BallNodeDelegate,你说明了这一点   class将符合该协议。所以,如果你在GameScene中做到了   没有didClick func它会导致错误。所有这些都被放入了   这样你就可以轻松地在你的人之间进行交流   BallNode实例和您的GameScene类(无需传递   围绕每个BallNode的GameScene引用)。每个BallNode   然后有一个委托(GameScene)你可以传回来   信息到。

在您的BallNode课程中

确保您拥有isUserInteraction = true

在您的BallNode类之外的

创建一个协议,将触摸信息发送回GameScene

protocol BallNodeDelegate: class {
    func didClick(ball: BallNode)
}

在BallNode类中创建一个委托变量

weak var delegate: BallNodeDelegate!

移动触摸开始你的BallNode类

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

    self.delegate?.didClick(ball: self)
}
GameScene中的

将合规性添加到BallNode协议

class GameScene: SKScene, BallNodeDelegate
当你创建一个Ball时,在GameScene中

确保你设置了它的代表

let ball = BallNode()
ball.delegate = self

在GameScene中添加嵌套。用于处理点击的func

func didClick(ball: BallNode) {
    print("clicked ball")
}

答案 1 :(得分:1)

您正在将完全触摸点与节点的完全位置进行比较,这些位置不太可能相同。

if positionOfTouch == node.position {

相反,您需要进行测试,以确定用户的触摸是否足够接近到球的位置。

一种选择是使用SKNode的{​​{1}}函数,它将为您处理此问题。

contains

旁注:您可能希望使用if node.contains(positionOfTouch) { 代替SKSpriteNode,因为SKShapeNode在SpriteKit中的效果不佳。

答案 2 :(得分:0)

查看nodes(at:CGPoint)处定义的SKNode,以检索触摸位置的节点列表。但是,您需要使用convertPoint(fromView)在视图坐标和场景坐标之间进行转换。文档herehere