Swift:检测 bodyAtPoint。总是零

Posted

技术标签:

【中文标题】Swift:检测 bodyAtPoint。总是零【英文标题】:Swift: detecting bodyAtPoint. Always nil 【发布时间】:2014-06-05 09:43:43 【问题描述】:

我很难发现为什么我无法使用 SpriteKit 检测到 bodyAtPointbodyAtPoint 总是返回 nil,即使它看起来我总是在点击精灵节点。

代码如下:

...

let spaceship = SKSpriteNode(color: UIColor.blueColor(), size: CGSizeMake(100, 100))

override func didMoveToView(view: SKView) 
    /* Setup your scene here */

    var borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    self.physicsBody = borderBody
    self.physicsBody.friction = 0.0
    self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)

    spaceship.name = "spaceship"
    spaceship.position = CGPointMake(400, 300)

    var bodySize = CGSizeMake(spaceship.size.width / 1.15, spaceship.size.height / 1.15);
    spaceship.physicsBody = SKPhysicsBody(rectangleOfSize: bodySize)

    spaceship.physicsBody.dynamic = false
    spaceship.physicsBody.restitution = 1.0
    spaceship.physicsBody.friction = 0.0
    spaceship.physicsBody.linearDamping = 0.0
    spaceship.physicsBody.allowsRotation = false

    self.addChild(spaceship)


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

    /* Called when a touch begins */
    super.touchesBegan(touches, withEvent: event)

    var touch : UITouch! = touches.anyObject() as UITouch
    var touchLocation : CGPoint! = touch.locationInNode(self)

    if self.physicsWorld.bodyAtPoint(touchLocation) 
        NSLog("true")
     else 
        NSLog("false")
    


...

结果:

spaceship.physicsBody 输出:

<SKPhysicsBody> type:<Rectangle> representedObject:[<SKSpriteNode> name:'spaceship' texture:['nil'] position:400, 300 size:100, 100 rotation:0.00]

touchLocation 输出:

(411.943664550781,553.014099121094)

self.physicsWorld.bodyAtPoint(touchLocation) 总是:

nil

...因此条件总是返回false

谁能解释我哪里出错了?我想最终检测到精灵节点上的触摸并执行操作。

编辑:

即使我简化为以下内容,我仍然总是得到false

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

    ...

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

        if self.physicsWorld.bodyAtPoint(location) 
            NSLog("true")
         else 
            NSLog("false")
        
    


...

【问题讨论】:

SpriteKit 是从左上角使用原点还是需要将其还原为左下角? @eXhausted 很抱歉,但我不确定... 还有一种方法叫做self.physicsWorld.bodyInRect,如果你是从SKNode继承的,请尝试调用self.physicsWorld.bodyInRect(self.frame)。它会返回一些值吗? 也可以使用:let location = touch.locationInNode(self) let nodeAtPoint = self.nodeAtPoint(location) println("NODE AT POINT: \(nodeAtPoint)") @eXhausted 非常感谢!我已经用答案更新了帖子。 【参考方案1】:

如果你想完全使用bodyAtPoint,你不能访问节点的名字。问题是,如果您想要像素完美的触摸检测,例如,您需要检测形状而不是带有 alpha 部分的精灵的矩形。

诀窍是使用 categoryBitMask。例如,您可以将类别 0x1

        let nodo = self.physicsWorld.bodyAtPoint(punto)
        if (nodo?.categoryBitMask == 0x1 << 1) 

        

这么简单!希望对你有帮助!

【讨论】:

【参考方案2】:

非常感谢@eXhausted 的回答。

诀窍是调用 nodeAtPoint 并访问 nodeAtPoint.name。

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

    for touch: AnyObject in touches 

        let location: CGPoint! = touch.locationInNode(self)

        let nodeAtPoint = self.nodeAtPoint(location)

        if nodeAtPoint.name 
            println("NODE FOUND: \(nodeAtPoint.name)")
         else 
            println("NULL")
        

    


【讨论】:

如果是可选的,您将需要使用nodeAtPoint.name!。如果它不是 Optional 则 if nodeAtPoint.name 没有意义,因此需要更改。 这并不能真正解释为什么 bodyAtPoint 不起作用,实际上是在做一些不同的事情。它找到一个 SKNode,其框架与该点相交,与附加到 SKNode 的 SKPhysicsBody 相对。 SKNode 累积帧不一定等于物理体路径,这意味着这两个“替代方案”并不总是产生相同的结果。我之所以提出这个问题,是因为我在 swift 中对这些方法没有运气,但过去使用 Objective-c 代码时使用它们没有问题。【参考方案3】:

当节点接近另一个带有附加粒子发射器的节点时,我遇到了类似的问题。似乎nodeAtPoint() 检测到了发射器,即使它当时是隐藏的。

我通过使用替代 nodesAtPoint() 并遍历节点来解决这个问题,直到找到我真正想要检测的节点。

不确定粒子发射器是否将其带到堆栈顶部的 z 顺序,但不想在此阶段摆弄 z 顺序,找到接触点处的所有接触节点对我有用。

【讨论】:

以上是关于Swift:检测 bodyAtPoint。总是零的主要内容,如果未能解决你的问题,请参考以下文章

Swift 函数不会很快返回

Swift中的Network Reachability

iOS 图表子类 Markerview 使用 Swift 总是在“xxx-Swift.h”中构建错误

iOS 图表子类 Markerview 使用 Swift 总是在“xxx-Swift.h”中构建错误

swift Swift - 检测边缘滑动

Swift:TextFields 总是显示布局约束错误 [重复]