[英]How to define category bit mask enumeration for SpriteKit in Swift?
要在 Objective-C 中定义类别位掩码枚举,我曾经键入:
typedef NS_OPTIONS(NSUInteger, CollisionCategory)
{
CollisionCategoryPlayerSpaceship = 0,
CollisionCategoryEnemySpaceship = 1 << 0,
CollisionCategoryChickenSpaceship = 1 << 1,
};
如何使用Swift
实现相同的目标? 我尝试了枚举,但无法使其正常工作。 这是我到目前为止所尝试的。
你可以做的是使用二进制文字: 0b1
, 0b10
, 0b100
,等等。
然而,在 Swift 中你不能按位或枚举,所以在枚举中使用位掩码真的没有意义。 查看此问题以替代 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
}
然后在您的播放器类中添加一个物理体并设置碰撞检测
physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(size.width, size.height))
physicsBody.categoryBitMask = ColliderType.Player.toRaw()
physicsBody.contactTestBitMask = ColliderType.Attacker.toRaw()
physicsBody.collisionBitMask = ColliderType.Attacker.toRaw()
并且对于您的攻击者类(或射弹、鸟、流星等),将其物理体设置为
physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
physicsBody.categoryBitMask = ColliderType.Attacker.toRaw()
physicsBody.contactTestBitMask = ColliderType.Player.toRaw()
physicsBody.collisionBitMask = ColliderType.Player.toRaw()
(请注意,您可以将物理体设置为您想要的任何形状)
然后确保你有一个SKPhysicsContactDelegate
设置(例如你可以让你的场景成为didBeginContact
)然后实现可选的协议方法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 将始终相同)
无论如何,一旦他们摆脱了 UInts 的错误,这将起作用
enum 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
我更喜欢使用下面这样的方法,它工作得很好,我认为这是最接近您最初尝试的方法:
// MARK: Categories - UInt32
let playerCategory:UInt32 = 0x1 << 0
let obstacleCategory:UInt32 = 0x1 << 1
let powerUpCategory:UInt32 = 0x1 << 2
PS:这是 Swift 4
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.