如何在Swift中为SpriteKit定义类别位掩码枚举?

要在Objective-C中定义类别位掩码枚举,我曾经输入:

typedef NS_OPTIONS(NSUInteger, CollisionCategory) { CollisionCategoryPlayerSpaceship = 0, CollisionCategoryEnemySpaceship = 1 << 0, CollisionCategoryChickenSpaceship = 1 << 1, }; 

如何使用Swift实现相同的目标? 我尝试了枚举,但无法使其正常工作。 这是我到目前为止所尝试的。

错误截图

你可以做的是使用二进制文字: 0b100等。

但是,在Swift中你不能按位OR枚举,所以在枚举中使用位掩码确实没有意义。 查看此问题以替换NS_OPTION。

如果你看一下这个swift教程 ,可以使用以下命令来避免整个toRaw()或rawValue转换:

 struct PhysicsCategory { static let None : UInt32 = 0 static let All : UInt32 = UInt32.max static let Monster : UInt32 = 0b1 // 1 static let Projectile: UInt32 = 0b10 // 2 } monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster monster.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile monster.physicsBody?.collisionBitMask = PhysicsCategory.None 

看看AdvertureBuilding SpriteKit游戏。 他们在Swift中重建了它,你可以在iOS8开发站点上下载源代码。

他们使用以下创建枚举的方法:

 enum ColliderType: UInt32 { case Hero = 1 case GoblinOrBoss = 2 case Projectile = 4 case Wall = 8 case Cave = 16 } 

设置就像这样

  physicsBody.categoryBitMask = ColliderType.Cave.toRaw() physicsBody.collisionBitMask = ColliderType.Projectile.toRaw() | ColliderType.Hero.toRaw() physicsBody.contactTestBitMask = ColliderType.Projectile.toRaw() 

并检查如下:

  func didBeginContact(contact: SKPhysicsContact) { // Check for Projectile if contact.bodyA.categoryBitMask & 4 > 0 || contact.bodyB.categoryBitMask & 4 > 0 { let projectile = (contact.bodyA.categoryBitMask & 4) > 0 ? contact.bodyA.node : contact.bodyB.node } } 

如上所述,user949350可以使用文字值。 但是他忘了指出的是你的原始价值应该是“正方形”。 请注意Apple的代码示例如何枚举类别。 它们分别为1,2,4,8和16,而不是通常的1,2,3,4,5等。

所以在你的代码中它应该是这样的:

 enum CollisionCategory:UInt32 { case PlayerSpaceShip = 1, case EnemySpaceShip = 2, case ChickenSpaceShip = 4, 

}

例如,如果您希望您的玩家节点与敌人或鸡太空船发生碰撞,您可以执行以下操作:

 playerNode.physicsBody.collisionBitMask = CollisionCategory.EnemySpaceShip.toRaw() | CollisionCategory.ChickenSpaceShip.toRaw() 

尝试将您的案例转换为UInt。

 enum CollisionCategory: UInt{ case PlayerSpaceship = 0 case EnemySpaceship = UInt(1 << 0) case PlayerMissile = UInt(1 << 1) case EnemyMissile = UInt(1 << 2) } 

这为我摆脱了错误。

在swift中处理位掩码的一种简单方法是创建一个包含所有不同碰撞类型的UInt32类型的枚举。 那是

 enum ColliderType: UInt32 { case Player = 1 case Attacker = 2 } 

然后在你的Player类中添加一个物理体并设置碰撞检测

 physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(size.width, size.height)) physicsBody.categoryBitMask = ColliderType.Player.toRaw() physicsBody.contactTestBitMask = ColliderType.Attacker.toRaw() physicsBody.collisionBitMask = ColliderType.Attacker.toRaw() 

对于你的攻击者类 (或射弹,鸟类,meteor等),将其物理体设置为

 physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2) physicsBody.categoryBitMask = ColliderType.Attacker.toRaw() physicsBody.contactTestBitMask = ColliderType.Player.toRaw() physicsBody.collisionBitMask = ColliderType.Player.toRaw() 

(请注意,您可以将物理主体设置为您想要的任何形状)

然后确保你有一个SKPhysicsContactDelegate设置(例如你可以让你的场景成为委托)然后实现可选的协议方法didBeginContact

 class GameScene: SKScene, SKPhysicsContactDelegate { override func didMoveToView(view: SKView) { physicsWorld.contactDelegate = self // Additional setup... } func didBeginContact(contact: SKPhysicsContact!) { println("A collision was detected!") if (contact.bodyA.categoryBitMask == ColliderType.Player.toRaw() && contact.bodyB.categoryBitMask == ColliderType.Attacker.toRaw()) { println("The collision was between the Player and the Attacker") } } } 

通过添加更多ColliderTypes,您可以在游戏中检测到更多碰撞。

UInt有一点错误,但考虑到我认为只使用了32位,这可行。 我还建议提交一个雷达,你应该可以使用任何常数值(1 << 2将始终是相同的)

无论如何,一旦他们摆脱了UI的错误,这将是有效的

枚举CollisionCategory:Int {case PlayerSpaceship = 0,EnemySpaceShip,PlayerMissile,EnemyMissile

 func collisionMask()->Int{ switch self{ case .PlayerSpaceship: return 0; default: return 1 << (self.toRaw()-1) } } } CollisionCategory.PlayerMissle.collisionMask() 

带有枚举的Swift 3:

 enum PhysicsCategory: UInt32 { case none = 1 case monster = 2 case projectile = 4 case wall = 8 } monster.physicsBody?.categoryBitMask = PhysicsCategory.monster.rawValue monster.physicsBody?.contactTestBitMask = PhysicsCategory.projectile.rawValue monster.physicsBody?.collisionBitMask = PhysicsCategory.none.rawValue