【问题标题】:Sprite-Kit: color xor logic with two sprites. black + black = whiteSprite-Kit:具有两个精灵的颜色异或逻辑。黑色 + 黑色 = 白色
【发布时间】:2017-09-23 21:51:53
【问题描述】:

你知道益智游戏“voi”吗?那是一款使用颜色异或逻辑的游戏。这意味着:黑色+黑色=白色。

https://www.youtube.com/watch?v=Aw5BdVcAtII

有没有办法用 sprite kit 中的两个 sprite 节点做相同的颜色逻辑?

谢谢。

【问题讨论】:

    标签: ios colors sprite-kit xor


    【解决方案1】:

    当然,在 Sprite Kit 中可以做到这一点。

    问题:

    假设您有 2 个黑色方块,squareAsquareB。用户可以将这两个方块拖动到任何他想要的地方。他一次只能拖动一个方块。每当两个正方形相交时,您都希望将相交区域着色为白色。

    初始设置:

    在场景的顶部,我们需要创建一些变量:

    private var squareA: SKSpriteNode?
    private var squareB: SKSpriteNode?
    private var squares = [SKSpriteNode]()
    private var selectedShape: SKSpriteNode?
    private var intersectionSquare: SKShapeNode?
    
    • squareAsquareB 只是我们最初在屏幕上看到的两个方块。
    • squares 是一个数组,它将存储屏幕上显示的所有方块。
    • selectedShape 将帮助我们跟踪当前正在拖动的方块。
    • intersectionSquare 是一个白色方块,代表两个黑色方块的交集区域。

    然后初始化squareAsquareB,并将它们添加到squares数组中,如下所示:

        squareA = SKSpriteNode(color: .black, size: CGSize(width: 190.0, height: 190.0))
    
        if let squareA = self.squareA {
            squareA.position = CGPoint(x: -200, y: 200)
            squareA.name = "Square A"
            squares.append(squareA)
            self.addChild(squareA)
        }
    
        // Do the same for squareB or any other squares that you have on screen..
    

    注意:如您所见,我在这里给它起了一个名字,只是为了在测试阶段更容易区分它们。

    检测用户何时拖动方块:

    现在,您需要检测用户何时拖动方块。为此,您可以使用:

        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            for t in touches { self.touchDown(atPoint: t.location(in: self)) }
        }
    
        override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
            for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
        }
    
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
            for t in touches { self.touchUp(atPoint: t.location(in: self)) }
        }
    
        override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
            for t in touches { self.touchUp(atPoint: t.location(in: self)) }
        }
    

    这些只是帮助我们的生活更轻松的方法。

    然后,您需要设置touchDowntouchMovedtouchUp 方法:

     func touchDown(atPoint pos : CGPoint) {
    
            let touchedNode = self.nodes(at: pos)
    
            guard let selectedSquare = touchedNode.first as? SKSpriteNode else {
                return
            }
    
            selectedShape = selectedSquare
        }
    
        func touchMoved(toPoint pos : CGPoint) {
    
            guard let selectedSquare = self.selectedShape else {
                return
            }
    
            selectedSquare.position = pos
    
            checkIntersectionsWith(selectedSquare)
        }
    
        func touchUp(atPoint pos : CGPoint) {
            selectedShape = nil
        }
    

    为了更详细地向您解释这里发生了什么:

    • touchDown方法中:

    好吧,我们需要用户一次只能拖动一个方块。使用nodes(at:) 方法,很容易知道触摸了哪个方格,我们可以知道将我们的selectedShape 变量设置为等于被触摸的方格。

    • touchMoved 方法中:

    这里我们基本上只是将selectedShape 移动到用户移动手指的位置。我们还调用checkIntersectionsWith() 方法,我们将在稍后设置。

    • touchUp 方法中:

    用户将手指从屏幕上松开,因此我们可以将selectedShape 设置为nil。

    改变相交框的颜色:

    现在让你的游戏看起来像你想要的最重要的部分是,当两个黑色方块相交时,如何将交叉框的颜色更改为白色?

    嗯,这里有不同的可能性,这是一种可能的方法:

    private func checkIntersectionsWith(_ selectedSquare: SKSpriteNode) {
    
        for square in squares {
    
            if selectedSquare != square && square.intersects(selectedSquare) {
    
                let intersectionFrame = square.frame.intersection(selectedSquare.frame)
    
                intersectionSquare?.removeFromParent()
                intersectionSquare = nil
    
                intersectionSquare = SKShapeNode(rect: intersectionFrame)
    
                guard let interSquare = self.intersectionSquare else {
                    return
                }
    
                interSquare.fillColor = .white
                interSquare.strokeColor = .clear
                self.addChild(interSquare)
    
            }  else if selectedSquare != square {
    
                intersectionSquare?.removeFromParent()
                intersectionSquare = nil
            }
        }
    }
    

    每次调用checkIntersectionsWith() 方法时,我们都会遍历squares 数组中的节点,并使用框架的intersection() 方法检查选定的正方形是否与其中任何一个相交(除了自己)。如果是,那么我们创建一个名为intersectionSquare 的白色正方形,并将其框架设置为等于相交框架。

    为了节省内存使用,您可以从场景中删除正方形,如果根本没有交叉点,则将intersectionSquare 设置为nil

    最终结果:

    最终结果如下所示:

    这只是我制作的快速草稿,向您展示您可以解决问题,显然您可以添加或改进很​​多东西(将其应用于屏幕上不仅有 2 个方块而且有很多方块的情况,或者当你的用户从屏幕上松开手指时产生一种磁性效果等),但我希望至少它能让你的项目走上正确的轨道:)

    【讨论】:

    • 太棒了!非常感谢
    猜你喜欢
    • 2015-09-18
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 2015-11-21
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    相关资源
    最近更新 更多