Cómo definir la categoría de máscara de bits de la enumeración de SpriteKit en Swift?

Para definir una categoría de máscara de bit enum en Objective-C que he usado para escribir:

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

¿Cómo puedo lograr el mismo uso de Swift? Experimenté con enumeraciones, pero no puede conseguir que funcione. Aquí es lo que he intentado hasta ahora.

Cómo definir la categoría de máscara de bits de la enumeración de SpriteKit en Swift?

InformationsquelleAutor RaffAl | 2014-06-05

9 Kommentare

  1. 19

    Lo que usted podría hacer es usar el binario literales: 0b1, 0b10, 0b100, etc.

    Sin embargo, en Swift no puede or bit a bit de las enumeraciones, así que realmente no hay punto en el uso de máscaras en las enumeraciones. Echa un vistazo esta pregunta para un reemplazo para NS_OPTION.

    • Como otras respuestas sugieren, puede utilizar enumeraciones siempre que utilice los valores sin procesar.
    • ¿qué valores sin procesar parece? Lo siento, no sé. Yo pensé que podría ser 0b0001, pero obviamente no.
    • rawValue es una «propiedad» de una enumeración que devuelve el real valor crudo utilizado para representar un caso de una enumeración. Si usted pide un caso específico de una enumeración no va a devolver un valor real, sino más bien la categoría en la que fue asignado. Así, por ejemplo, dada una enumeración de «Fruta» con el caso de «banana», que fue igual a 0b100, si usted imprime el valor de «Fruta.banana» devolverá «banana», pero si imprime el valor de «Fruta.el plátano.rawValue» se imprimirá el valor real, 4.
    • Gracias @daver. Voy a tener que cogitate en esto, y extraer un par de veces, a continuación, tratar de visualizar lo que yo estaba tratando de dibujar… entonces tal vez esto va a tener sentido para mí. El diseñador de cerebro tiene ENORMES problemas con la nebulousness, opacidad y la pura arbitrariedad de la programación de los paradigmas y procesos.
    • No se preocupe, creo que la idea clave a entender es justo que Swift enumeraciones están intentando duro para conseguir que simplemente tratarlos como categorías, es decir, sólo los nombres no son los números o valores, y sólo si usted realmente, realmente, realmente quiero saber el verdadero valor’ que se almacena debajo, a continuación, Swift te obliga a usar .rawValue a ver que.
    • GRACIAS! Esa es una información útil. La otra parte del problema podría ser que en realidad nunca he visto formas de uso de las enumeraciones claramente, como un medio para resolver problemas. Son el triple de reliant, en mi forma de pensar: la Estructura de los mismos, por definición, la aclaración de configuración//obtención de un valor y, a continuación, prueba/control de este. Parece una innecesaria artificio, la mayoría del tiempo.
    • así que estoy todavía tienen que «aha!», momento en el que me recibe por ello el uso de ellos, y sólo los uso porque creo que debo tratar de asimilar, más que de forma innata de ver a un propósito y lugar para ellos.
    • Creo que el «problema» de que la enumeración concepto fue originalmente concebido para resolver fue el ambiguo uso arbitrario de números enteros para representar categorías/nombres/conceptos que aparecen en la ramificación de las condiciones. Por ejemplo, en C, la única cosa que usted puede utilizar en una sentencia switch() es un tipo int, por lo que si usted necesita para sucursal con sede en alguna categoría, que sólo se puede utilizar 1, 2, 3. Enumeración permite cambiar el nombre de 1, 2, 3 como «la bola», «cuadrado», «triángulo». Por lo tanto el código dice que «si (la bola), a continuación,…. «en lugar de «si (1) entonces …» Básicamente, sólo hace que el código sea más legible.
    • Pero en swift enumeraciones tienen mucho más capacidad de simplemente dar una lectura de la etiqueta a un número sin sentido, ya que son más como structs&clases: pueden tener métodos, y también puede agrupar varios valores al mismo tiempo y tratarlos como una sola entidad. Realmente no puedo hacer justicia en un comentario, usted debe leer la de apple, swift libro en las enumeraciones para ver lo que pueden hacer, son realmente muy potente. (excepto, al parecer, para el uso de una máscara de bits, entonces son todavía bastante torpe 🙁

  2. 19

    Si usted mira este tutorial swift, usted puede evitar todo el toRaw() o rawValue de conversión mediante el uso de:

    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 
  3. 9

    Echar un vistazo a la AdvertureBuilding SpriteKit juego. La reconstruyeron en Swift y se puede descargar el código fuente en la iOS8 dev sitio.

    Están utilizando el siguiente método de creación de una enumeración:

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

    Y la instalación es como este

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

    Y comprobar como esta:

    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
        }
    }
  4. 4

    Como señaló, user949350 puede utilizar los valores literales en su lugar. Pero lo que él se olvidó de señalar es que su valor crudo debe estar en «cuadrados». Observe cómo la muestra de código de Apple enumera las categorías. Ellos son 1, 2, 4, 8 y 16, en lugar de la habitual de 1, 2, 3, 4 , 5 etc.

    Así que en el código debería ser algo como esto:

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

    }

    Y si usted quiere que su jugador nodo a chocar con el enemigo o el pollo de la nave espacial, por ejemplo, usted puede hacer algo como esto:

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

    Tratar de fundición sus casos como UInt.

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

    Esto elimina los errores para mí.

    • He copiado el código, pero sigo obteniendo el mismo error que he publicado en la captura de pantalla. No cambió nada.
    • Interesante. Así que usted puede, por omisión, siempre que usando únicamente los literales 1,2,4,8 etc
  6. 1

    Una forma sencilla de gestionar las máscaras de bits en swift es crear una enumeración de tipo UInt32 que contiene todos los diferentes tipos de colisión. Que es

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

    Y, a continuación, en su la Clase de Jugador agregar una física del cuerpo y la configuración de la detección de colisiones

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

    Y para su Atacante de Clase (o un proyectil, un pájaro, un meteoro, etc.) el programa de instalación de su física del cuerpo como

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

    (Tenga en cuenta que la configuración física del cuerpo a cualquier forma que usted desee)

    A continuación, asegúrese de que usted tiene un SKPhysicsContactDelegate de instalación (por ejemplo, usted puede dejar que su escena el delegado) y, a continuación, implementar el opcional método de protocolo de 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")
            }
    
        }
    
    }

    Mediante la adición de más ColliderTypes puede detectar colisiones más en su juego.

    • Gracias, una buena explicación..
    • La máscara de bits de los valores de la enumeración debe ser cuadrados de 2, a la derecha? Si es así, tal vez resaltar esto para futuros lectores que suponga el siguiente valor de su ejemplo podría ser el de 3.
  7. 0

    Hay un poco de un error con UInt, pero dado que creo que sólo de 32 bits se utilizan de todos modos que esto iba a funcionar. También me gustaría sugerir la presentación de un radar, usted debería ser capaz de usar cualquier valor constante (1 << 2 siempre será el mismo)

    De todos modos, aquí está, una vez que han conseguido deshacerse de los bichos con UInts, este trabajo

    enum CollisionCategory: Int{
    caso PlayerSpaceship = 0, EnemySpaceShip, PlayerMissile, EnemyMissile

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

    Swift 3 con enum:

    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 
  9. 0

    Yo prefiero usar como el de abajo, que funciona bien y creo que es la manera más próxima a su tentativa original:

    //MARK: Categories - UInt32
    let playerCategory:UInt32 = 0x1 << 0
    let obstacleCategory:UInt32 = 0x1 << 1
    let powerUpCategory:UInt32 = 0x1 << 2

    P. S.: Esto es Swift 4

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea