Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.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 使用SpriteKit停止对象碰撞_Swift_Sprite Kit - Fatal编程技术网

Swift 使用SpriteKit停止对象碰撞

Swift 使用SpriteKit停止对象碰撞,swift,sprite-kit,Swift,Sprite Kit,我正在测试SpriteKit的功能,遇到了一个问题。我在读《比特面具》、《碰撞》、《分类》和《接触》。我知道它们是什么,至少大部分情况下,我不明白分类位掩码的意义,但我得到了冲突位掩码,这是我需要解决我的问题 我的问题是我有两种不同类型的精灵:对象和第二种。这些名字没有多大意义,但只是为了测试。我希望第二个物体有一个冲动,我希望物体有一个力。我能够在精灵上应用各自的向量,但我不希望它们相互碰撞。我想让他们直接通过,忽略彼此的存在 我试图通过相互分配不同的冲突位掩码来解决该问题: override

我正在测试SpriteKit的功能,遇到了一个问题。我在读《比特面具》、《碰撞》、《分类》和《接触》。我知道它们是什么,至少大部分情况下,我不明白分类位掩码的意义,但我得到了冲突位掩码,这是我需要解决我的问题

我的问题是我有两种不同类型的精灵:对象和第二种。这些名字没有多大意义,但只是为了测试。我希望第二个物体有一个冲动,我希望物体有一个力。我能够在精灵上应用各自的向量,但我不希望它们相互碰撞。我想让他们直接通过,忽略彼此的存在

我试图通过相互分配不同的冲突位掩码来解决该问题:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let texture = SKTexture(imageNamed: "pokeball")
    let object = SKSpriteNode(texture: texture)

    object.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: object.size.width,height: object.size.height))
    object.physicsBody?.affectedByGravity = false
    object.yScale = 0.5
    object.xScale = 0.5

    for t in touches {
        object.position = t.location(in: self)
    }
    self.addChild(object)
    object.physicsBody?.collisionBitMask = UInt32(4)
    object.physicsBody?.applyForce(CGVector(dx: 0, dy: 10))

}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    let texture = SKTexture(imageNamed: "purple")
    let second = SKSpriteNode(texture: texture)
    let impulse : Double = 20
    let x = (impulse * Double(cosf(45)))
    let y = Double(impulse * Double(sinf(45)))
    let vector = CGVector(dx: x, dy: y)
    second.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: second.size.width,height: second.size.height))

    second.yScale = 1.5
    second.xScale = 1.5
    second.physicsBody?.isDynamic = true

    for t in touches {
        second.position = t.location(in: self)
    }
    self.addChild(second)
    second.physicsBody?.collisionBitMask = UInt32(1)
    second.physicsBody?.applyImpulse(vector)
}
第二个的位掩码为1:

second.physicsBody?.collisionBitMask = UInt32(1)
我运行了模拟器,但它们仍在相互碰撞,所以我上网试图寻找一些答案:我找到了一个答案,上面说我必须使用如下数字:

这些是位掩码,不能使用任意数字1、2、3、4、5-必须使用1、2、4、8、16等等-

有人能解释一下原因吗?然而,这不是问题所在,因为我使用的是1和4

我遇到的下一个问题是我必须使用二进制数(0100)和(0010),我尝试了它们,同样的问题:仍然冲突

我将留下碰撞的照片:


有人知道为什么会这样吗?如果这是一个非常愚蠢的错误或已经被问到的问题,我会提前道歉。我就是找不到它。

有很多关于这些主题的文档,但这里有一个实际的例子

分类的力量 假设您有一个由三个节点组成的集合
pool
basketball
bowlingball
。现在,很明显,我们希望篮球和保龄球互相碰撞。因此,您可以这样设置碰撞位掩码:

basketball.physicsBody?.collisionBitMask    = UInt32(2)
bowlingball.physicsBody?.collisionBitMask   = UInt32(2)
太好了。现在,我们希望
保龄球
沉入
池底
篮球
相撞(可能更像是水花,但请耐心等待)。我们怎么做?我们可以尝试:

pool.physicsBody?.collisionBitMask = UInt32(2) // ?
但是等等,那会使
篮球和
保龄球与
游泳池发生碰撞。我们只希望
篮球
与游泳池发生碰撞,而
保龄球
忽略
游泳池
并直接沉入池底而不发生碰撞。这就是
categoryBitMask
s派上用场的地方:

let basketballBitMask     = UInt32(1)
let bowlingballBitMask    = UInt32(2)
let poolBitMask           = UInt32(4)  // Why 4? See next section

basketball.physicsBody?.categoryBitMask    = basketballBitMask
bowlingball.physicsBody?.categoryBitMask   = bowlingballBitMask
pool.physicsBody?.categoryBitMask          = poolBitMask
因为每个对象都有一个指定给它的唯一编号,所以现在可以拾取并选择希望另一个对象与之碰撞的对象:

// basketball physics body collides with bowlingball(2) OR pool(4)
basketball.physicsBody?.collisionBitMask    = bowlingballBitMask | poolBitMask
// ( '|' = logical OR operator)

// bowlingball physics body only collides with basketball(1)
bowlingball.physicsBody?.collisionBitMask   = basketballBitMask

// pool physics body only collides with basketball(1)
pool.physicsBody?.collisionBitMask          = basketballBitmask
如果您不确定奇怪的“|”符号在做什么,我强烈建议使用高级运算符来帮助您了解这里发生了什么

为什么不直接使用冲突位掩码呢? 好的,我们设置了一些小面具。但是它们是如何使用的呢?如果我们只有两个对象,为什么我们不能比较collisionBitMasks呢

简单地说,这不是它的工作原理。当
保龄球
接触时,SpriteKit物理引擎会将
保龄球
类别比特掩码
的碰撞比特掩码(反之亦然;结果相同):

由于
bowlingball
categoryBitMask
pool
collisionBitMask
共有零位,
objectsshouldclide
等于零,SpriteKit将阻止对象碰撞

但是,在您的情况下,您没有设置对象的
categoryBitMask
s。因此,它们的默认值为2^32,或0xFFFFFF(),或二进制值为0B11111111111111。因此,当“对象”撞击“第二个”对象时,SpriteKit会执行以下操作:

objectsShouldCollide = (0b11111111111111111111111111111111 & // Default categoryBitMask for "object" 
                        0b00000000000000000000000000000001)  // collisionBitMask for "second" object
//                   =  0b00000000000000000000000000000001
因此,当您尚未定义
对象的categoryBitMask时,无论您将什么设置为
第二个
对象的
碰撞位掩码
,objectsShouldCollide将永远不会为零,并且始终会发生碰撞

注意:您可以将对象的
冲突位掩码设置为0;但是那样的话,这个物体就永远无法与任何物体碰撞

对CategoryBitMask使用2的幂(0,1,2,4,8等) 现在让我们假设我们想要包含多个相互碰撞的
保龄球。简单:

bowlingball.physicsBody?.collisionBitMask  = basketballBitMask | bowlingballBitMask
// bowlingball collision bit mask (in binary)  = 0b10 | 0b01 = 0b11
// bowlingball collision bit mask (in decimal)  = 2 | 1 = 3 
在这里您可以看到,如果我们将
pool
s physicacscategory设置为UInt32(3),它将不再与
bowlingball
basketball
区分开来

进一步建议 学会有目的地使用变量,即使您只是在使用它们进行测试(尽管巧合的是,“
object
second
object”工作得很好)

使用位掩码结构简化代码并提高可读性:

struct PhysicsCategory {
    static let Obj1         : UInt32 = 0b1 << 0
    static let Obj2         : UInt32 = 0b1 << 1
    static let Obj3         : UInt32 = 0b1 << 2
    static let Obj4         : UInt32 = 0b1 << 3
}

obj1.physicsBody?.categoryBitmask = PhysicsCategory.Obj1 // etc
结构物理分类{
静态let Obj1:UInt32=0b1为什么不下载并使用这个简单的精灵工具包项目呢?它创建各种几何形状,将其中一些设置为碰撞,一些设置为接触,使用
checkPhysics()
函数显示将要发生的事情,然后让您随意切换这些形状


任何关于其工作原理的问题,我都很乐意尝试解释。

看看这个:查找category bit mask的默认值。这里已经解释过了。指定一个物理体的collisionBitMAsk为4只意味着它与categoryBitMask为4的物理体发生碰撞(事实上,设置了'4'位,但让我们从最简单的示例开始)。如果您不想看到任何CategoryBitMask,事情就不会发生了。我不明白为什么我可以直接进入碰撞位掩码时,您需要类别位掩码?请您解释一下吗?好像不是
bowlingball.physicsBody?.collisionBitMask  = basketballBitMask | bowlingballBitMask
// bowlingball collision bit mask (in binary)  = 0b10 | 0b01 = 0b11
// bowlingball collision bit mask (in decimal)  = 2 | 1 = 3 
struct PhysicsCategory {
    static let Obj1         : UInt32 = 0b1 << 0
    static let Obj2         : UInt32 = 0b1 << 1
    static let Obj3         : UInt32 = 0b1 << 2
    static let Obj4         : UInt32 = 0b1 << 3
}

obj1.physicsBody?.categoryBitmask = PhysicsCategory.Obj1 // etc