简体   繁体   English

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

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

I'm new to Swift so apologies if I have made a rookie error. 我是Swift的新手,如果我犯了菜鸟错误就道歉了。 I am trying to get two boxes to disappear when they touch if the two boxes are the same color. 如果两个盒子的颜色相同,我试图让两个盒子在触摸时消失。 I have the following code so far: 到目前为止,我有以下代码:

This code sets up the game: 此代码设置游戏:

    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)

        }

Code to generate a random color: 用于生成随机颜色的代码:

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

This is the part that matters - the actual contact between the objects: 这是重要的部分 - 对象之间的实际联系:

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

And finally the code for when the user touches the screen: 最后是用户触摸屏幕时的代码:

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

I have provided all the code so you know the setup. 我提供了所有代码,因此您了解设置。 Thank you in advance for your help. 预先感谢您的帮助。

You haven't set contactBitMask appropriately so no contacts were detected... By default, due to performance reasons a default value of this mask is zero: 您尚未正确设置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. 当两个实体共享相同的空间时,通过执行逻辑AND操作,针对另一个主体的接触掩码测试每个主体的类别掩码。 If either comparison results in a nonzero value, an SKPhysicsContact object is created and passed to the physics world's delegate. 如果任一比较结果为非零值,则创建SKPhysicsContact对象并将其传递给物理世界的委托。 For best performance, only set bits in the contacts mask for interactions you are interested in. 为获得最佳性能,只需在联系人掩码中设置您感兴趣的交互位。

The default value is 0x00000000 (all bits cleared). 默认值为0x00000000(所有位清零)。

To fix this, set both contact and category bit masks to an appropriate values, like this: 要解决此问题,请将联系人和类别位掩码设置为适当的值,如下所示:

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

Now when a contact happen between two bodies, as said in docs, each body's category bit mask is tested agains the other body's contact mask, by performing logical AND operation. 现在,当两个实体之间发生接触时,如文档中所述,通过执行逻辑AND操作,每个主体的类别位掩码将再次测试另一个主体的接触掩码。 If a result is non-zero, a contact notification occurs. 如果结果非零,则发生联系通知。 In this case this would be 1 & 1 = 1. 在这种情况下,这将是1&1 = 1。

First, declare a struct for the categoryBitMask : 首先,声明categoryBitMaskstruct

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

Second, change you enum declaration to the following: 其次,将枚举声明更改为以下内容:

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

I just changed the above code to return Color instead of UIColor . 我刚刚更改了上面的代码以返回Color而不是UIColor

Third, modify didBegin to: 第三,将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()
    }
}

In the above code, just compare the categoryBitMask is enough as I will set the body with same color with same categoryBitMask later. 在上面的代码中,只需比较categoryBitMask就足够了,因为稍后我将使用相同的categoryBitMask设置相同颜色的主体。

Lastly, set the categoryBitMask to the box using the following code: 最后,使用以下代码将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)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何检测两个物体何时相互接触? - How to detect when two objects touch each other? 如何检测相同类型的节点彼此连续接触(SpriteKit) - How to detect same types of nodes touching each other consecutively (SpriteKit) 什么是检查两个或更多CGRects在NSMutableArray中时是否触摸的好方法? - What is a good way to check if two or more CGRects touch when they are in a NSMutableArray? 在数组中查找具有相同颜色的元素,如果元素彼此相邻,则显示true - Find elements in array with the same color and print true if they are next to each other CGColor-从彼此重叠的两个UIView确定混合颜色 - CGColor - Determining the blended color from two UIViews that are on top of each other 当您同时触摸两个按钮时会发生什么 - What happens when you touch two buttons at the same time 如何在贝塞尔曲线路径内检查彼此重叠显示的多个UIView子视图? - How do I check multiple UIView subviews displayed on top of each other for a touch event inside a bezier path? SpriteKit / Swift - 如何在两个节点已经接触时检查它们的接触 - SpriteKit / Swift - How to check contact of two nodes when they are already in contact 如何检查两个运动物体是否相互碰撞IOS - How to check if two moving objects collide each other IOS 检查两个NSArray是否包含彼此的对象(NSManagedObject) - Check two NSArrays for containing each other's objects (NSManagedObject)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM