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

Check if two nodes are the same color when they touch each other

我是 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)
            }
        }

我已经提供了所有代码以便您了解设置。预先感谢您的帮助。

首先,为 categoryBitMask 声明一个 struct:

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]
    }
}

我只是把上面的代码改成return 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就足够了,因为我稍后会设置相同颜色的body与相同的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)
    }
}

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

When two bodies share the same space, each body’s category mask is tested against the other body’s contact mask by performing a logical AND operation. If either comparison results in a nonzero value, an SKPhysicsContact object is created and passed to the physics world’s delegate. For best performance, only set bits in the contacts mask for interactions you are interested in.

The default value is 0x00000000 (all bits cleared).

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

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)
        }
    }
}

现在,当两个物体之间发生接触时,如文档中所述,通过执行逻辑与运算,每个物体的类别位掩码将再次测试另一个物体的接触掩码。如果结果不为零,则会发生联系通知。在这种情况下,这将是 1 & 1 = 1.