Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 检测节点是否接触框架的最佳方法_Swift_Sprite Kit_Sknode_Skshapenode - Fatal编程技术网

Swift 检测节点是否接触框架的最佳方法

Swift 检测节点是否接触框架的最佳方法,swift,sprite-kit,sknode,skshapenode,Swift,Sprite Kit,Sknode,Skshapenode,我正在用SpriteKit制作一些游戏,其中包括作为SKShapeNode的球。我创建了一个类来定义球及其属性(包括SKPhysicsBody)。球应该在屏幕上运行,框架是屏幕边界(使用edgeLoopFrom:self.frame)。我还创建了一个位于屏幕顶部的路径节点。现在,我想这样做,如果一些球到达帧的顶部边界,那么一些函数将执行。 我读了一些关于它的文章,但我不确定什么是正确的方法,如果使用contactBitMask,或者是否有其他更好的选择。 如果正确的方法是通过contactBit

我正在用SpriteKit制作一些游戏,其中包括作为SKShapeNode的球。我创建了一个类来定义球及其属性(包括SKPhysicsBody)。球应该在屏幕上运行,框架是屏幕边界(使用edgeLoopFrom:self.frame)。我还创建了一个位于屏幕顶部的路径节点。现在,我想这样做,如果一些球到达帧的顶部边界,那么一些函数将执行。 我读了一些关于它的文章,但我不确定什么是正确的方法,如果使用contactBitMask,或者是否有其他更好的选择。 如果正确的方法是通过contactBitMask-我必须为balls节点设置一个结构,还是可以在它们的类中设置它?
谢谢

如果我没有弄错,当球击中位于屏幕上半部分的路径节点时,您希望调用一个函数

首先,我不确定路径节点是否比sprite节点更有效,事实上我从未真正使用过路径节点,但这里是您可以做的

查看上面的链接。您需要做的是实现skphysiccontactdelegate。这将允许您访问函数didbeing()和didEnd()。在physicsworld中进行接触时调用这些函数

class YourClass: SKScene, SKPhysicsContactDelegate {
    func didBegin(_ contact: SKPhysicsContact) {
    }

    func didEnd(_ contact: SKPhysicsContact) {
    }
}
为了调用这些函数,需要将physicsworld的contactDelegate设置为将处理调用的类。这将是您的场景,设置该场景的好地方是didMove()函数

class YourClass: SKScene, SKPhysicsContactDelegate {
    func didMove(to view: SKView) {
        physicsWorld.contactDelegate = self
    }
现在,当发生可检测的接触时,将调用didbeagin(),当接触结束时,将调用didEnd()

现在我们需要给我们的节点一些物理体,我们可以在它们上设置不同的位掩码,以便检测碰撞/接触。以下是我们关注的3个位掩码:

categoryTestBitMask
collisionTestBitMask
contactTestBitMask
categoryTestBitMask:您可以为类似类型的节点指定一个类别,例如“ball”可以是该类别。所有不同的球对象都可以具有相同的类别。我使用“noCollision”类别来表示何时我想检测到联系人,但我不想发生碰撞。你被限制在32个不同的类别,尽管如此,不要去疯狂与吨不同的

碰撞测试位掩码:为您的“球”指定一个您希望发生碰撞的类别。例如:将“球”的collisiontestmask设置为“墙”的类别位掩码。碰撞是指两个对象在物理上相互碰撞;所以你的球会从墙上弹下来

contactTestBitMask:当两个节点重叠时,将显示一个联系人。因此,它将调用代理的接触方法,而不是球从某物上反弹。请注意,可以将碰撞位掩码和接触位掩码设置为同一对象

现在我们如何设置这些面具。我使用一个结构,这样我就可以为位掩码分配名称,并用代码设置这3个不同的掩码。大概是这样的:

struct Mask {
static var ball: UInt32 = 0b10 //2
static var wall: UInt32 = 0b100 //4
static var pathNode: UInt32 = 0b1000 //8
}
现在,您可以在代码中设置掩码:

let ball = SKSpriteNode()
ball.name = "ball"
ball.physicsBody = SKPhysicsBody()
ball.physicsBody.categoryTestBitMask = Mask.ball
ball.physicsBody.collisionTestBitMask = Mask.wall
ball.physicsBody.contactTestBitMask = Mask.pathNode | Mask.wall

let pathNode = SKSpriteNode()
pathNode.name = "pathNode"
pathNode.physicsBody = SKPhysicsBody()
pathNode.physicsBody.categoryTestBitMask = Mask.pathNode
pathNode.physicsBody.collisionTestBitMask = 0
pathNode.physicsBody.contactTestBitMask = Mask.pathNode
让我们看看我们在这里说什么。我们创建一个ball对象,并将其类别设置为“ball”,我们说我们希望它与“wall”对象发生碰撞,我们希望我们的联系人代理函数与“pathNode”对象或“wall”对象触发。我们的pathNode对象将没有碰撞,并且将与球有接触

基本上,球将从墙上反弹,并将通过pathNode。它将使用pathNode和wall对象调用contact委托函数didbeagin()和didend()

还没有完成。。。那么当调用函数时,我们如何处理这个问题呢?当调用DIDBENG或didend函数时,它有一个参数“contact”。此contact param有两个要处理的实体,它们是相互接触的实体。我们有多种方法可以解决这个问题,但我现在只给大家介绍一种简单的方法

func didBegin(_ contact: SKPhysicsContact) {
    if contact.bodyA!.node!.name == "ball" {
    // bodyA is our ball
        switch contact.bodyB!.node!.name {
        case "pathNode":
            thisIsMyBallHitPathNodeFunction()
        case "wall":
            thisIsMyBallHitWallFunction()
        default:
            break
        }
    }
    else if contact.bodyB!.node!.name == "ball" {
    // bodyB is our ball
        switch contact.bodyA!.node!.name {
        case "pathNode":
            thisIsMyBallHitPathNodeFunction()
        case "wall":
            thisIsMyBallHitWallFunction()
        default:
            break
        }

    }

}
更新: 我们现在要做的是找出bodyA和bodyB的类型。所以它从bodyA开始,如果bodyA是一个“球”,那么我们知道bodyA是一个“球”,bodyB是球接触到的东西。然后我们使用switch语句来确定bodyB是什么。一旦我们知道bodyB是什么,我们就调用我们需要调用的函数来实现这两个节点之间的特定接触

然后,您只需将代码放入您想要执行的那些指定函数中


如果你是新来的,我建议你尝试一下,试着让它发挥作用。之后,我会在youTube上播放一些关于如何做到这一点的视频。看看不同的人如何处理同一件事是个好主意,然后你可以自己决定怎么做。这可能不是最优雅的处理方式他与人接触,但效果很好,经过一些练习,它将成为第二天性,祝你好运!

非常感谢。它起作用了!继续这个问题我问了另一个问题[link][link]这个答案能解决我的第二个问题吗?我会看一看,很高兴能帮上忙!你能解释一下“didbeagin”函数是如何工作的吗?我不明白bodyA和bodyB的含义和用法。如果你在答案中通读了这个链接,它应该会再看一遍。另外,如果你在理解上有困难,也可以观看一些youtube视频。但基本上,当游戏中的两个节点之间存在接触时,会触发DidBeagin。bodyA和bodyB是接触的两个节点PhysicsBody。函数不知道它们是什么类型的节点,这就是为什么需要检查(我对if语句做了什么)。