Sprite-Kit:带有两个精灵的颜色异或逻辑。黑色 + 黑色 = 白色

Sprite-Kit: color xor logic with two sprites. black + black = white

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

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

在sprit kit中有没有什么办法可以对两个sprite节点做同样的颜色逻辑?

谢谢。

当然,可以在 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 只是我们最初出现在屏幕上的 2 个方块。
  • 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 个而且有很多方块的情况在屏幕上,或者当你的用户从屏幕上松开他的手指时创建一种磁力效果等)但我希望至少它会让你的项目走上正轨:)