SKPhysicsContactDelegate使用Swift进行碰撞检测

时间:2015-12-13 22:39:17

标签: swift sprite-kit skphysicsbody skphysicscontact

我正在尝试修复我在SKPhysicsContactDelegate碰撞检测中遇到的问题。我有两个节点,nodeA和nodeB,nodeA在屏幕上是静止的,而nodeB可以被用户的手指在屏幕上拖动。 nodeA需要能够检测nodeB是否与它重叠。 didBeginContact和didEndContact方法被多次调用,通过研究我发现这是一种预期的行为。为了解决这个问题,我只需将一个整数变量设置为0,并在每次有联系时递增它,并在每次联系结束时递减它。如果该值大于0,则两个节点重叠,如果该值等于0,则它们不重叠。这种方法很好,直到用户在nodeA上拖动nodeB太快。发生这种情况时,联系方式并不总是称为正确的次数。例如,可能检测到3个联系人但只有两个结束联系人(甚至没有联系人),这使得程序认为两个节点仍然重叠,即使它们不是。我假设发生这种情况是因为用户拖动节点的速度比程序可以更新的速度快。我能做些什么来解决这个问题吗?基本上我只需要知道两个节点何时重叠以及何时不重叠。还要注意节点是凸形的。以下是我的联系方式:

func didBeginContact(contact: SKPhysicsContact)
{
    let contactMask = contact.bodyA.categoryBitMask + contact.bodyB.categoryBitMask

    if contactMask == 3
    {
        startContact++
        timerStart = true
    }
}

func didEndContact(contact: SKPhysicsContact)
{
    let contactMask = contact.bodyA.categoryBitMask + contact.bodyB.categoryBitMask

    if contactMask == 3
    {
        startContact--
        if startContact == 0
        {
            timerStart = false
        }
    }
} 

1 个答案:

答案 0 :(得分:1)

您可以使用intersectsNode:方法检查一个节点是否与另一个节点相交。关于这种方法的文档:

  

返回一个布尔值,指示此节点是否相交   指定的节点。

另外要记住的重要部分是:

  

如果两个节点的帧相交,则认为它们相交。   在此测试中将忽略两个节点的子节点。

import SpriteKit

class GameScene: SKScene {


    var stationaryNode :SKSpriteNode = SKSpriteNode(color: SKColor.grayColor(), size: CGSize(width: 100, height: 100))

    var moveableNode   :SKSpriteNode = SKSpriteNode(color: SKColor.purpleColor(), size: CGSize(width: 100, height: 100))

    let debugLabel     :SKLabelNode  = SKLabelNode(fontNamed: "ArialMT")

    override func didMoveToView(view: SKView) {


        setupScene()

    }

    func setupScene(){

        stationaryNode.name = "stationaryNode"
        stationaryNode.zRotation = 0.2
        stationaryNode.zPosition = 1
        stationaryNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
        addChild(stationaryNode)

        moveableNode.name = "moveableNode"
        moveableNode.zRotation = 0.4
        moveableNode.zPosition = 2
        moveableNode.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)-200)
        addChild(moveableNode)

        debugLabel.fontSize = 18
        debugLabel.fontColor = SKColor.yellowColor()
        debugLabel.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)+200)
        addChild(debugLabel)
        updateDebugLabel()


    }

    func updateDebugLabel(){

        let intersectionDetected:String = stationaryNode.intersectsNode(moveableNode) ? "YES" : "NO"

        debugLabel.text = "Overlapping : " + intersectionDetected

    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {


        for touch in touches {

            let location = touch.locationInNode(self)

            let previousPosition = touch.previousLocationInNode(self)

            let node: SKNode? = nodeAtPoint(location)

            if let nodeName = node?.name{

                if nodeName == "moveableNode" {

                    let translation = CGPoint(x: location.x - previousPosition.x , y: location.y - previousPosition.y )

                    node!.position = CGPoint(x: node!.position.x + translation.x, y: node!.position.y + translation.y)

                }
            }

        }
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */


        updateDebugLabel()

    }
}

我猜这个解决方案比使用物理引擎检测这种快速移动物体的触点要好一些。尽管如此,快速移动物体可能会产生不可预测的结果。

相关问题