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

问题描述:

你知道益智游戏“voi”吗?这是一款适用于color-XOR逻辑的游戏。这意味着:黑+黑=白。Sprite-Kit:带有两个子画面的颜色异或逻辑。黑+黑=白

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

有没有办法做同样的颜色逻辑与精神试剂盒检验两种精灵节点?

谢谢。

当然,在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为零。

更改路口框的颜色:

现在最重要的组成部分,使您的游戏其实像你想的人,是怎样的交集框的颜色更改为白色时,两个黑色方块相交?

好了,你有不同的可能性在这里,并在这里是做这件事的一种可能的方式:

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,如果根本没有交集。

最终结果:

最后的结果是这样的:

enter image description here

这只是一个快速的草案,我做给你看的,你可以处理这个问题,显然有很多东西可以添加或改进(将其应用于屏幕上不仅有2个但有许多方格的情况,或者在用户从屏幕释放手指时产生一种磁性效果等),但我希望至少它会把你放在正确的轨道为您的项目:)

+1

太棒了!非常感谢你 – Yann