我正在测试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)
}
因此对象的位掩码为4:
object.physicsBody?.collisionBitMask = UInt32(4)
第二个位掩码为1:
second.physicsBody?.collisionBitMask = UInt32(1)
我跑了模拟器,他们仍然相互碰撞,所以我上网并试图寻找答案:我找到了一个说我必须使用的数字:
这些是位掩码,你不能使用任意数字1,2,3,4,5 - 你必须使用1,2,4,8,16等等 -
有人可以解释原因吗?但是,这不是问题,因为我使用的是1和4
我遇到的下一个问题说我必须使用二进制数字(0100)和(0010),我试过它们,同样的问题:仍然发生碰撞。
我将留下碰撞图片: Collisions
有谁知道为什么会这样?如果这是一个非常愚蠢的错误或已经被问到的事情,我提前道歉,我就是找不到它。
答案 0 :(得分:8)
有很多关于这些主题的文档,但这是一个实际的例子。
假设您有三个节点pool
,basketball
和bowlingball
的集合。现在,显然,我们希望basketball
和bowlingball
相互冲突。所以你像这样设置collisionBitMasks:
basketball.physicsBody?.collisionBitMask = UInt32(2)
bowlingball.physicsBody?.collisionBitMask = UInt32(2)
大。现在,我们希望bowlingball
下沉到pool
的底部,basketball
与pool
发生碰撞(可能更多的是引起轰动,但要忍受我)。我们怎么做?我们可以试试:
pool.physicsBody?.collisionBitMask = UInt32(2) // ?
但请稍等,这会使basketball
和bowlingball
与pool
发生冲突。我们只希望basketball
与池冲突,而我们希望bowlingball
忽略pool
并直接沉到底部而不会发生冲突。这是categoryBitMask
派上用场的地方:
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
如果你不确定那些奇怪的&#39; |&#39;符号正在做,我强烈推荐高级操作符swift documentation来帮助您了解这里发生的事情。
好的,我们设置了一些位掩码。但他们是如何使用的呢?如果我们只有两个对象,为什么我们只能比较collisionBitMasks?
简单地说,这不是它的工作原理。当bowlingball
与pool
联系时,SpriteKit物理引擎会将bowlingball
categoryBitMask 与pool
的collisionBitMask(反之亦然;结果相同):
objectsShouldCollide = (bowlingball.physicsBody?.categoryBitMask &
pool.physicsBody?.collisionBitMask)
// objectsShouldCollide = (ob010 & 0b100) = 0b000
由于bowlingball
categoryBitMask
和pool
&#39; s collisionBitMask
共有零位,objectsShouldCollide
相等为零,SpriteKit将阻止物体碰撞。
但是,在您的情况下,您并未设置对象&#39; categoryBitMask
秒。因此它们的默认值为2 ^ 32或0xFFFFFFFF(hexadecimal representation)或二进制,0b1111111111111111111111111111111111。所以当一个&#34;对象&#34;击中第二个&#34;对象,SpriteKit这样做:
objectsShouldCollide = (0b11111111111111111111111111111111 & // Default categoryBitMask for "object"
0b00000000000000000000000000000001) // collisionBitMask for "second" object
// = 0b00000000000000000000000000000001
因此,当您没有定义object
的categoryBitMask时,无论您设置为second
对象collisionBitMask
,objectShouldCollide都会永远不会为零,他们总会碰撞。
注意:您可以将对象的collisionBitMask
设置为0;但那个对象永远不会与任何东西发生碰撞。
现在让我们说我们想要包含多个相互碰撞的bowlingball
个。易:
bowlingball.physicsBody?.collisionBitMask = basketballBitMask | bowlingballBitMask
// bowlingball collision bit mask (in binary) = 0b10 | 0b01 = 0b11
// bowlingball collision bit mask (in decimal) = 2 | 1 = 3
在这里你可以看到,如果我们将pool
的physicsCategory设置为UInt32(3),它就不再能与bowlingball
或basketball
区分开。
有目的地学习name变量,即使您只是使用它们进行测试(但巧合的是,&#34; object
和second
对象&#34;工作得很好。)
使用位掩码结构来简化代码并提高可读性:
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
答案 1 :(得分:2)
为什么不下载并使用这个简单的Sprite-Kit项目?它会创建各种几何形状,将其中一些设置为碰撞,一些设置为接触,使用#import <UIKit/UIKit.h>
@interface AddressListTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIView *viewAddressInfo;
@property (weak, nonatomic) IBOutlet UILabel *labelUsername;
@property (weak, nonatomic) IBOutlet UILabel *labelAddress;
@property (weak, nonatomic) IBOutlet UIImageView *imageViewRadioSelection;
@end
功能显示将要发生的事情,然后让您轻弹它们。
对于它的运作有任何疑问,我会非常乐意尝试解释。