如何在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