【问题标题】:prevent Spritekit nodes with the same Catagorymask from colliding防止具有相同 Catagorymask 的 Spritekit 节点发生碰撞
【发布时间】:2019-02-02 22:49:56
【问题描述】:

我有一个我正在处理的 Spritekit 项目,其中有一个玩家节点,你可以在屏幕上移动,然后有子弹节点向你射击。我的问题是子弹不仅会击中玩家,还会互相击中。我已经为玩家和子弹提供了他们自己的类别/碰撞/接触面罩。

我在这里指定了所有不同的类别掩码(其中一些可以忽略):

enum CategoryMask : UInt32 {
    case playeragain = 11
    case player = 1
    case GBullet = 2
    case BBullet = 3
    case enemyships = 4
    case coin = 5
    case boss = 6
}

BBullet 是向你射击的子弹,而 player 是用户控制的节点。

然后我将这些掩码分配给每个节点:

    player.physicsBody?.categoryBitMask = CategoryMask.player.rawValue
    player.physicsBody?.collisionBitMask = CategoryMask.BBullet.rawValue | CategoryMask.coin.rawValue
    player.physicsBody?.contactTestBitMask = CategoryMask.BBullet.rawValue | CategoryMask.coin.rawValue


    bullet.physicsBody?.categoryBitMask = CategoryMask.BBullet.rawValue
    bullet.physicsBody?.collisionBitMask = CategoryMask.player.rawValue
    bullet.physicsBody?.contactTestBitMask = CategoryMask.player.rawValue

子弹和玩家之间的碰撞工作正常,我已经在“开始接触”功能中设置了如何处理每次碰撞。我想指定我不希望子弹相互碰撞。

【问题讨论】:

    标签: swift sprite-kit collision categories skspritenode


    【解决方案1】:

    二进制位掩码。

    所以最好使用一些位运算符:

    enum CategoryMask : UInt32 {
    case playeragain = 0b00000001
    case player = 0b00000010
    case GBullet = 0b00000100
    case BBullet = 0b00001000
    case enemyships = 0b00010000
    case coin = 0b00100000
    case boss = 0b01000000
      }
    
    
    
       // case playeragain = 1<<0 //1
       // case player = 1<<1    // 2
        // case GBullet = 1<<2  // 4
       // case BBullet = 1<<3   //8
       // case enemyships = 1<<4 //16
       // case coin = 1<<5 //32
       // case boss = 1<<6 //64
    
      //
    

    这应该给你你真正的东西。

    这是 Apple Document 中的一个示例,红球会落地而蓝球不会。

        let ground = SKShapeNode()
    
          redBall.physicsBody?.collisionBitMask = 0b0001
          blueBall.physicsBody?.collisionBitMask = 0b0010
          ground.physicsBody?.categoryBitMask = 0b0001
    

    【讨论】:

    • 所以我听从了您的建议,将所有内容更改为您上面的内容,但遇到了一个新问题,我收到一堆错误消息:“无法将 'Int32' 类型的值分配给 'UInt32 '”并告诉我,“将 'CategoryMask.player.rawValue' 替换为 'UInt32(CategoryMask.player.rawValue)'”。所以我假设你把它们设为“Int32”是个错误,所以我把它改回了“UInt32”,但现在没有任何碰撞。我应该返回并按照错误所说的内容进行操作,还是应该将其保留为“UInt32”。
    • 更新:我按照错误给出的指示,当我运行程序时,没有任何碰撞。
    • 如果你对二进制不熟悉,就如上图那样计数比较。
    【解决方案2】:

    只是添加到上面的答案中,您对类别位掩码的定义为:

    case playeragain = 11 (binary 1011)
    case player = 1            (Binary 0001)
    case GBullet = 2.          (Binary 0010)
    case BBullet = 3.         (Binary 0011)
    case enemyships = 4. (Binary. 0100)
    case coin = 5.              (Binary 0101)
    case boss = 6.             (Binary 0110)
    

    您拥有的唯一唯一值(即设置一个位)是玩家、GBullet 和敌人。任何定义为 BBullet 的东西都将匹配为 player 或 GBullet; coin 将识别为敌人或玩家,boss 为敌人或 GBullet,玩家再次识别为未定义 (1000)、GBullet 或 Player。

    这里是碰撞和接触测试位掩码的指南: https://stackoverflow.com/a/40596890/1430420

    【讨论】:

      猜你喜欢
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 2018-01-31
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      相关资源
      最近更新 更多