Spritekit:使用手指画线时检测碰撞

Spritkit : Detect collision while drawing line using finger

我正在尝试检测 existing line 和用户 currently drawing using finger 之间的冲突 contactPoint

这是我的代码:

let padding: CGFloat = 100
override func didMove(to view: SKView) {

    physicsWorld.contactDelegate = self

    let startPoint1 = CGPoint(x: self.frame.minX + padding , y: self.frame.minY + padding)
    let leftHorizontalPoint = CGPoint(x: self.frame.minX + padding, y: self.frame.maxY - padding)

    let line1 = SKShapeNode()
    let line_path:CGMutablePath = CGMutablePath()
    line_path.move(to: startPoint1)
    line_path.addLine(to: leftHorizontalPoint)
    line1.path = line_path
    line1.lineWidth = 3
    line1.strokeColor = UIColor.white
    addChild(line1)

    line1.physicsBody = SKPhysicsBody(edgeLoopFrom: line1.frame)
    line1.physicsBody?.isDynamic = true
    line1.physicsBody?.categoryBitMask = PhysicsCategory.solidLine
    line1.physicsBody?.collisionBitMask = PhysicsCategory.currentLine
    line1.physicsBody?.contactTestBitMask = PhysicsCategory.currentLine
}

然后在 touchBegin、touchMove 和 touchEnd 上我有以下代码:

var currentLineNode: SKShapeNode!
var startPoint: CGPoint = CGPoint.zero
func touchDown(atPoint pos : CGPoint) {
    startPoint = pos
}

func touchMoved(toPoint pos : CGPoint) {
    if currentLineNode != nil {
        currentLineNode.removeFromParent()
    }
    currentLineNode = SKShapeNode()
    currentLineNode.zPosition = 1
    let line_path:CGMutablePath = CGMutablePath()
    line_path.move(to: startPoint)
    line_path.addLine(to: pos)
    currentLineNode.path = line_path
    currentLineNode.lineWidth = 3
    currentLineNode.strokeColor = UIColor.red
    addChild(currentLineNode)

    currentLineNode.physicsBody = SKPhysicsBody(edgeLoopFrom: currentLineNode.frame)
    currentLineNode.physicsBody?.isDynamic = true
    currentLineNode.physicsBody?.categoryBitMask = PhysicsCategory.currentLine
    currentLineNode.physicsBody?.collisionBitMask = PhysicsCategory.solidLine
    currentLineNode.physicsBody?.contactTestBitMask = PhysicsCategory.solidLine
}

func touchUp(atPoint pos : CGPoint) {
    if currentLineNode != nil {
        currentLineNode.removeFromParent()
    }
    currentLineNode = SKShapeNode()
    let line_path:CGMutablePath = CGMutablePath()
    line_path.move(to: startPoint)
    line_path.addLine(to: pos)
    currentLineNode.path = line_path
    currentLineNode.lineWidth = 3
    currentLineNode.strokeColor = UIColor.red
    addChild(currentLineNode)

    currentLineNode.physicsBody = SKPhysicsBody(edgeLoopFrom: currentLineNode.frame)
    currentLineNode.physicsBody?.isDynamic = true
    currentLineNode.physicsBody?.categoryBitMask = PhysicsCategory.currentLine
    currentLineNode.physicsBody?.collisionBitMask = PhysicsCategory.solidLine
    currentLineNode.physicsBody?.contactTestBitMask = PhysicsCategory.solidLine
}

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

    for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}

physicsWorld's contactDelegate 如下:(委托甚至没有执行)

extension GameScene : SKPhysicsContactDelegate {
    func didBegin(_ contact: SKPhysicsContact) {
       // This never get detected :(
       print(contact.contactPoint)
       var firstBody: SKPhysicsBody
       var secondBody: SKPhysicsBody
       if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
           firstBody = contact.bodyA
           secondBody = contact.bodyB
       } else {
           firstBody = contact.bodyB
           secondBody = contact.bodyA
       }
    }
}

这是我的输出,即使从白色线经过,它也没有检测到碰撞。

有什么问题吗?对此的任何建议都会有所帮助。

您正在使用 2 个基于边的实体。无论您是否设置,基于边的实体将始终为 isDynamic = false。您至少需要 1 个基于体积的物体才能执行接触。

此外,您还不断地删除和添加节点,这是一个糟糕的主意。

我建议仅在 touchesBegan 上添加您的节点,然后仅更新 touchesMoved 上的路径

您正在使用边缘循环创建物理 [​​=18=]。 Apple 将边缘循环定义为...

An edge has no volume or mass and is always treated as if the isDynamic property is equal to false. Edges may only collide with volume-based physics bodies.

将你的物理学body改成这样有效

currentLineNode.physicsBody = SKPhysicsBody(rectangleOf: currentLineNode.frame.size, center: CGPoint(x: startPoint.x + currentLineNode.frame.size.width / 2, y: startPoint.y + currentLineNode.frame.size.height / 2)) 

还应注意,在 touchesEnded 中更改物理 body 是多余的,不会增加任何内容。我从 touchesEnded 中删除了它,它工作正常