我正在努力发现为什么我无法通过SpriteKit检测到bodyAtPoint
。 bodyAtPoint
始终返回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")
}
}
}
...
答案 0 :(得分:1)
如果要完全使用bodyAtPoint,则无法访问节点的名称。问题是如果你想要像素完美的触摸检测,例如,你需要检测形状而不是带有alpha部分的精灵的矩形。
诀窍是使用 categoryBitMask 。您可以指定类别0x1&lt;&lt;例如,1,对象然后询问其类别。 Category是一个Uint32,具有与name相同的功能,主要用于物理碰撞检测,但你可以用它来识别物理身体:
let nodo = self.physicsWorld.bodyAtPoint(punto)
if (nodo?.categoryBitMask == 0x1 << 1) {
}
太容易了!希望它能帮到你!
答案 1 :(得分:0)
非常感谢@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")
}
}
}
答案 2 :(得分:0)
当节点接近另一个有附加粒子发射器的节点时,我遇到了类似的问题。似乎nodeAtPoint()
检测到了发射器,即使它当时被隐藏了。
我通过使用替代nodesAtPoint()
并迭代节点直到找到我真正想要检测的节点来解决这个问题。
如果粒子发射器将它带到堆栈的顶部,或者不想在此阶段摆弄z排序,不确定z顺序是否是z顺序,在触点处找到所有触摸的节点对我有效。