检查两个节点相互接触时是否颜色相同

时间:2017-03-02 09:13:13

标签: ios swift sprite-kit swift3 skspritenode

我是Swift的新手,如果我犯了一个菜鸟错误,请道歉。如果两个盒子的颜色相同,我试图让两个盒子在触摸时消失。到目前为止,我有以下代码:

此代码设置游戏:

    import SpriteKit
    import GameplayKit

    class GameScene: SKScene, SKPhysicsContactDelegate {
        override func didMove(to view: SKView) {
            physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
            physicsWorld.contactDelegate = self

            let background = SKSpriteNode(imageNamed: "background.jpg")
            background.size = self.frame.size;
            background.position = CGPoint(x: 0, y: 0)
            background.blendMode = .replace
            background.zPosition = -1
            addChild(background)

        }

生成随机颜色的代码:

        enum Color {
            case ColorRed
            case ColorGreen
            case ColorBlue

            public var color: UIColor {
                switch self {
                case .ColorRed: return UIColor(red: 255, green: 0, blue: 0, alpha: 1)
                case .ColorGreen: return UIColor(red: 0, green: 255, blue: 0, alpha: 1)
                case .ColorBlue: return UIColor(red: 0, green: 0, blue: 255, alpha: 1)
                }
            }

            static var all: [Color] = [.ColorRed, .ColorGreen, .ColorBlue]

            static var randomColor: UIColor {
                let randomIndex = Int(arc4random_uniform(UInt32(all.count)))
                return all[randomIndex].color
            }
        }

这是重要的部分 - 对象之间的实际联系:

    func didBegin(_ contact: SKPhysicsContact) {

        if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {

            let firstBody = contact.bodyA.node as! SKSpriteNode!
            let secondBody = contact.bodyB.node as! SKSpriteNode!

            if firstBody!.color == secondBody!.color {
                firstBody!.removeFromParent()
                secondBody!.removeFromParent()
            }
        } else {

            let firstBody = contact.bodyB.node as! SKSpriteNode!
            let secondBody = contact.bodyA.node as! SKSpriteNode!

            if firstBody!.color == secondBody!.color {
                firstBody!.removeFromParent()
                secondBody!.removeFromParent()
            }
        }
    }

最后是用户触摸屏幕时的代码:

        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            if let touch = touches.first {
                let location = touch.location(in: self)
                let box = SKSpriteNode(color: UIColor.red, size: CGSize(width: 64, height: 64))
                box.color = Color.randomColor
                box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 64, height: 64))
                box.position = location
                addChild(box)
            }
        }

我提供了所有代码,因此您了解了设置。提前感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

您尚未正确设置contactBitMask,因此未检测到任何联系人...默认情况下,由于性能原因,此掩码的默认值为零:

  

当两个物体共享相同的空间时,每个物体的类别掩码都是   通过执行逻辑来测试另一个身体的接触面罩   和操作。如果任一比较结果为非零值,则为   创建SKPhysicsContact对象并将其传递给物理世界   代表。为获得最佳性能,仅在触点掩码中设置位   您感兴趣的互动。

     

默认值为0x00000000(清除所有位)。

要解决此问题,请将联系人和类别位掩码都设置为适当的值,如下所示:

class GameScene: SKScene,SKPhysicsContactDelegate {

    override func didMove(to view: SKView) {
        self.physicsWorld.contactDelegate = self

        physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
        physicsWorld.contactDelegate = self


    }

    func didBegin(_ contact: SKPhysicsContact) {

        if let bodyA = contact.bodyA.node as? SKSpriteNode,
           let bodyB = contact.bodyB.node as? SKSpriteNode{
            //Of course this is simple example and you will have to do some "filtering" to determine what type of objects are collided.
           // But the point is , when appropriate objects have collided, you compare their color properties.
            if bodyA.color == bodyB.color {
                bodyA.run(SKAction.removeFromParent())
                bodyB.run(SKAction.removeFromParent())
            }
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let location = touch.location(in: self)
            let box = SKSpriteNode(color: UIColor.red, size: CGSize(width: 64, height: 64))
            box.color = Color.randomColor

            box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 64, height: 64))
            box.physicsBody?.contactTestBitMask = 0b1
            box.physicsBody?.categoryBitMask = 0b1
            box.position = location
            addChild(box)
        }
    }
}

现在当两个机构之间发生接触时,如文档中所述,通过执行逻辑AND操作,每个机体的类别位掩码再次测试另一个机构的接触掩模。如果结果非零,则发生联系通知。在这种情况下,这将是1&amp; 1 = 1。

答案 1 :(得分:0)

首先,为struct声明categoryBitMask

struct ColorMask {
    static let Red: UInt32 = 0x1 << 0
    static let Green: UInt32 = 0x1 << 1
    static let Blue: UInt32 = 0x1 << 2
}

其次,将枚举声明更改为以下内容:

enum Color {
    case ColorRed
    case ColorGreen
    case ColorBlue

    public var color: UIColor {
        switch self {
        case .ColorRed: return UIColor(red: 255, green: 0, blue: 0, alpha: 1)
        case .ColorGreen: return UIColor(red: 0, green: 255, blue: 0, alpha: 1)
        case .ColorBlue: return UIColor(red: 0, green: 0, blue: 255, alpha: 1)
        }
    }

    static var all: [Color] = [.ColorRed, .ColorGreen, .ColorBlue]

    static var randomColor: Color {
        let randomIndex = Int(arc4random_uniform(UInt32(all.count)))
        return all[randomIndex]
    }
}

我刚刚更改了上面的代码以返回Color而不是UIColor

第三,将didBegin修改为:

func didBegin(_ contact: SKPhysicsContact) {
    if contact.bodyA.categoryBitMask == contact.bodyB.categoryBitMask {
        let firstBody = contact.bodyA.node as! SKSpriteNode!
        let secondBody = contact.bodyB.node as! SKSpriteNode!

        firstBody!.removeFromParent()
        secondBody!.removeFromParent()
    }
}

在上面的代码中,只需比较categoryBitMask即可,因为稍后我会将相同的颜色设置为相同的categoryBitMask

最后,使用以下代码将categoryBitMask设置为框:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let location = touch.location(in: self)
        let box = SKSpriteNode(color: UIColor.red, size: CGSize(width: 64, height: 64))
        let color = Color.randomColor
        box.color = color.color
        box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 64, height: 64))
        if color == Color.ColorRed {
            box.physicsBody?.categoryBitMask = ColorMask.Red
        } else if color == Color.ColorGreen {
            box.physicsBody?.categoryBitMask = ColorMask.Green
        }else if color == Color.ColorBlue {
            box.physicsBody?.categoryBitMask = ColorMask.Blue
        }
        box.physicsBody?.contactTestBitMask = ColorMask.Red | ColorMask.Green | ColorMask.Blue
        box.position = location
        addChild(box)
    }
}